Commit 37f36147 authored by Vadim Zeitlin's avatar Vadim Zeitlin Committed by Ronan

Add logger class to allow customizing SOCI logging operations.

No big changes yet, but it is now possible to use a custom logger object which
may do something else than just write the query string passed to it to a
stream.

The old behaviour is preserved by using the standard SOCI logger by default
which does write the query to the stream.
parent 2752cc7d
//
// Copyright (C) 2014 Vadim Zeitlin
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef SOCI_LOGGER_H_INCLUDED
#define SOCI_LOGGER_H_INCLUDED
#include "soci/soci-platform.h"
#include <ostream>
namespace soci
{
// Allows to customize the logging of database operations performed by SOCI.
//
// To do it, derive your own class from logger_impl and override its pure
// virtual start_query() and do_clone() methods (overriding the other methods
// is optional), then call session::set_logger() with a logger object using
// your implementation.
class SOCI_DECL logger_impl
{
public:
logger_impl() {}
virtual ~logger_impl();
// Called to indicate that a new query is about to be executed.
virtual void start_query(std::string const & query) = 0;
logger_impl * clone() const;
// These methods are for compatibility only as they're used to implement
// session basic logging support, you should only override them if you want
// to use session::set_stream() and similar methods with your custom logger.
virtual void set_stream(std::ostream * s);
virtual std::ostream * get_stream() const;
virtual std::string get_last_query() const;
private:
// Override to return a new heap-allocated copy of this object.
virtual logger_impl * do_clone() const = 0;
// Non-copyable
logger_impl(logger_impl const &);
logger_impl & operator=(logger_impl const &);
};
// A wrapper class representing a logger.
//
// Unlike logger_impl, this class has value semantics and can be manipulated
// easily without any danger of memory leaks or dereferencing a NULL pointer.
class SOCI_DECL logger
{
public:
// No default constructor, must always have an associated logger_impl.
// Create a logger using the provided non-NULL implementation (an exception
// is thrown if the pointer is NULL). The logger object takes ownership of
// the pointer and will delete it.
logger(logger_impl * impl);
logger(logger const & other);
logger& operator=(logger const & other);
~logger();
void start_query(std::string const & query) { m_impl->start_query(query); }
// Methods used for the implementation of session basic logging support.
void set_stream(std::ostream * s) { m_impl->set_stream(s); }
std::ostream * get_stream() const { return m_impl->get_stream(); }
std::string get_last_query() const { return m_impl->get_last_query(); }
private:
logger_impl * m_impl;
};
} // namespace soci
#endif // SOCI_LOGGER_H_INCLUDED
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "soci/once-temp-type.h" #include "soci/once-temp-type.h"
#include "soci/query_transformation.h" #include "soci/query_transformation.h"
#include "soci/connection-parameters.h" #include "soci/connection-parameters.h"
#include "soci/logger.h"
// std // std
#include <cstddef> #include <cstddef>
...@@ -86,7 +87,17 @@ public: ...@@ -86,7 +87,17 @@ public:
set_query_transformation_(qtf); set_query_transformation_(qtf);
} }
// support for basic logging // Support for custom logging of database operations.
// Set the custom logger to use.
void set_logger(logger const & logger);
// Return the currently used logger, by default, this is an instance of a
// standard SOCI logger.
logger const & get_logger() const;
// support for basic logging (use set_logger() for more control).
void set_log_stream(std::ostream * s); void set_log_stream(std::ostream * s);
std::ostream * get_log_stream() const; std::ostream * get_log_stream() const;
...@@ -182,8 +193,7 @@ private: ...@@ -182,8 +193,7 @@ private:
std::ostringstream query_stream_; std::ostringstream query_stream_;
details::query_transformation_function* query_transformation_; details::query_transformation_function* query_transformation_;
std::ostream * logStream_; logger logger_;
std::string lastQuery_;
connection_parameters lastConnectParameters_; connection_parameters lastConnectParameters_;
......
//
// Copyright (C) 2014 Vadim Zeitlin
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#define SOCI_SOURCE
#include "soci/logger.h"
#include "soci/error.h"
using namespace soci;
namespace // anonymous
{
// Helper to throw from not implemented logger_impl methods.
void throw_not_supported()
{
throw soci_error("Legacy method not supported by this logger.");
}
} // namespace anonymous
logger_impl * logger_impl::clone() const
{
logger_impl * const impl = do_clone();
if (!impl)
{
throw soci_error("Cloning a logger implementation must work.");
}
return impl;
}
logger_impl::~logger_impl()
{
}
void logger_impl::set_stream(std::ostream * s)
{
throw_not_supported();
}
std::ostream * logger_impl::get_stream() const
{
throw_not_supported();
return NULL;
}
std::string logger_impl::get_last_query() const
{
throw_not_supported();
return std::string();
}
logger::logger(logger_impl * impl)
: m_impl(impl)
{
if (!m_impl)
{
throw soci_error("Null logger implementation not allowed.");
}
}
logger::logger(logger const & other)
: m_impl(other.m_impl->clone())
{
}
logger& logger::operator=(logger const & other)
{
logger_impl * const implOld = m_impl;
m_impl = other.m_impl->clone();
delete implOld;
return *this;
}
logger::~logger()
{
delete m_impl;
}
...@@ -26,17 +26,63 @@ void ensureConnected(session_backend * backEnd) ...@@ -26,17 +26,63 @@ void ensureConnected(session_backend * backEnd)
} }
} }
// Standard logger class used by default.
class standard_logger_impl : public logger_impl
{
public:
standard_logger_impl()
{
logStream_ = NULL;
}
virtual void start_query(std::string const & query)
{
if (logStream_ != NULL)
{
*logStream_ << query << '\n';
}
lastQuery_ = query;
}
virtual void set_stream(std::ostream * s)
{
logStream_ = s;
}
virtual std::ostream * get_stream() const
{
return logStream_;
}
virtual std::string get_last_query() const
{
return lastQuery_;
}
private:
virtual logger_impl* do_clone() const
{
return new standard_logger_impl;
}
std::ostream * logStream_;
std::string lastQuery_;
};
} // namespace anonymous } // namespace anonymous
session::session() session::session()
: once(this), prepare(this), query_transformation_(NULL), logStream_(NULL), : once(this), prepare(this), query_transformation_(NULL),
logger_(new standard_logger_impl),
uppercaseColumnNames_(false), backEnd_(NULL), uppercaseColumnNames_(false), backEnd_(NULL),
isFromPool_(false), pool_(NULL) isFromPool_(false), pool_(NULL)
{ {
} }
session::session(connection_parameters const & parameters) session::session(connection_parameters const & parameters)
: once(this), prepare(this), query_transformation_(NULL), logStream_(NULL), : once(this), prepare(this), query_transformation_(NULL),
logger_(new standard_logger_impl),
lastConnectParameters_(parameters), lastConnectParameters_(parameters),
uppercaseColumnNames_(false), backEnd_(NULL), uppercaseColumnNames_(false), backEnd_(NULL),
isFromPool_(false), pool_(NULL) isFromPool_(false), pool_(NULL)
...@@ -46,7 +92,8 @@ session::session(connection_parameters const & parameters) ...@@ -46,7 +92,8 @@ session::session(connection_parameters const & parameters)
session::session(backend_factory const & factory, session::session(backend_factory const & factory,
std::string const & connectString) std::string const & connectString)
: once(this), prepare(this), query_transformation_(NULL), logStream_(NULL), : once(this), prepare(this), query_transformation_(NULL),
logger_(new standard_logger_impl),
lastConnectParameters_(factory, connectString), lastConnectParameters_(factory, connectString),
uppercaseColumnNames_(false), backEnd_(NULL), uppercaseColumnNames_(false), backEnd_(NULL),
isFromPool_(false), pool_(NULL) isFromPool_(false), pool_(NULL)
...@@ -56,7 +103,8 @@ session::session(backend_factory const & factory, ...@@ -56,7 +103,8 @@ session::session(backend_factory const & factory,
session::session(std::string const & backendName, session::session(std::string const & backendName,
std::string const & connectString) std::string const & connectString)
: once(this), prepare(this), query_transformation_(NULL), logStream_(NULL), : once(this), prepare(this), query_transformation_(NULL),
logger_(new standard_logger_impl),
lastConnectParameters_(backendName, connectString), lastConnectParameters_(backendName, connectString),
uppercaseColumnNames_(false), backEnd_(NULL), uppercaseColumnNames_(false), backEnd_(NULL),
isFromPool_(false), pool_(NULL) isFromPool_(false), pool_(NULL)
...@@ -65,7 +113,8 @@ session::session(std::string const & backendName, ...@@ -65,7 +113,8 @@ session::session(std::string const & backendName,
} }
session::session(std::string const & connectString) session::session(std::string const & connectString)
: once(this), prepare(this), query_transformation_(NULL), logStream_(NULL), : once(this), prepare(this), query_transformation_(NULL),
logger_(new standard_logger_impl),
lastConnectParameters_(connectString), lastConnectParameters_(connectString),
uppercaseColumnNames_(false), backEnd_(NULL), uppercaseColumnNames_(false), backEnd_(NULL),
isFromPool_(false), pool_(NULL) isFromPool_(false), pool_(NULL)
...@@ -74,7 +123,9 @@ session::session(std::string const & connectString) ...@@ -74,7 +123,9 @@ session::session(std::string const & connectString)
} }
session::session(connection_pool & pool) session::session(connection_pool & pool)
: query_transformation_(NULL), logStream_(NULL), isFromPool_(true), pool_(&pool) : query_transformation_(NULL),
logger_(new standard_logger_impl),
isFromPool_(true), pool_(&pool)
{ {
poolPosition_ = pool.lease(); poolPosition_ = pool.lease();
session & pooledSession = pool.at(poolPosition_); session & pooledSession = pool.at(poolPosition_);
...@@ -244,6 +295,30 @@ void session::set_query_transformation_(cxx_details::auto_ptr<details::query_tra ...@@ -244,6 +295,30 @@ void session::set_query_transformation_(cxx_details::auto_ptr<details::query_tra
} }
} }
void session::set_logger(logger const & logger)
{
if (isFromPool_)
{
pool_->at(poolPosition_).set_logger(logger);
}
else
{
logger_ = logger;
}
}
logger const & session::get_logger() const
{
if (isFromPool_)
{
return pool_->at(poolPosition_).get_logger();
}
else
{
return logger_;
}
}
void session::set_log_stream(std::ostream * s) void session::set_log_stream(std::ostream * s)
{ {
if (isFromPool_) if (isFromPool_)
...@@ -252,7 +327,7 @@ void session::set_log_stream(std::ostream * s) ...@@ -252,7 +327,7 @@ void session::set_log_stream(std::ostream * s)
} }
else else
{ {
logStream_ = s; logger_.set_stream(s);
} }
} }
...@@ -264,7 +339,7 @@ std::ostream * session::get_log_stream() const ...@@ -264,7 +339,7 @@ std::ostream * session::get_log_stream() const
} }
else else
{ {
return logStream_; return logger_.get_stream();
} }
} }
...@@ -276,12 +351,7 @@ void session::log_query(std::string const & query) ...@@ -276,12 +351,7 @@ void session::log_query(std::string const & query)
} }
else else
{ {
if (logStream_ != NULL) logger_.start_query(query);
{
*logStream_ << query << '\n';
}
lastQuery_ = query;
} }
} }
...@@ -293,7 +363,7 @@ std::string session::get_last_query() const ...@@ -293,7 +363,7 @@ std::string session::get_last_query() const
} }
else else
{ {
return lastQuery_; return logger_.get_last_query();
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment