Skip to content

Commit

Permalink
Implement session::get_last_query_with_context()
Browse files Browse the repository at this point in the history
Fixes #678
Fixes #1027
  • Loading branch information
Krzmbrzl committed Aug 25, 2024
1 parent 4440c78 commit b148409
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 14 deletions.
14 changes: 14 additions & 0 deletions include/soci/logger.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ class SOCI_DECL logger_impl
// Called to indicate that a new query is about to be executed.
virtual void start_query(std::string const & query) = 0;

// Called to log a parameter that is bound to the currently active query
virtual void add_query_parameter(std::string name, std::string value) = 0;

virtual void reset_query_parameter() = 0;

logger_impl * clone() const;

// These methods are for compatibility only as they're used to implement
Expand All @@ -38,6 +43,7 @@ class SOCI_DECL logger_impl
virtual void set_stream(std::ostream * s);
virtual std::ostream * get_stream() const;
virtual std::string get_last_query() const;
virtual std::string get_last_query_with_context() const;

private:
// Override to return a new heap-allocated copy of this object.
Expand Down Expand Up @@ -68,10 +74,18 @@ class SOCI_DECL logger

void start_query(std::string const & query) { m_impl->start_query(query); }

virtual void add_query_parameter(std::string name, std::string value)
{
m_impl->add_query_parameter(std::move(name), std::move(value));
}

virtual void reset_query_parameter() { m_impl->reset_query_parameter(); }

// 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(); }
std::string get_last_query_with_context() const { return m_impl->get_last_query_with_context(); }

private:
logger_impl * m_impl;
Expand Down
3 changes: 3 additions & 0 deletions include/soci/session.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,10 @@ class SOCI_DECL session
std::ostream * get_log_stream() const;

void log_query(std::string const & query);
void reset_query_parameter();
void add_query_parameter(std::string name, std::string value);
std::string get_last_query() const;
std::string get_last_query_with_context() const;

void set_got_data(bool gotData);
bool got_data() const;
Expand Down
7 changes: 7 additions & 0 deletions src/core/logger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ std::string logger_impl::get_last_query() const
SOCI_DUMMY_RETURN(std::string());
}

std::string logger_impl::get_last_query_with_context() const
{
throw_not_supported();

SOCI_DUMMY_RETURN(std::string());
}

logger::logger(logger_impl * impl)
: m_impl(impl)
{
Expand Down
79 changes: 79 additions & 0 deletions src/core/session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ void ensureConnected(session_backend * backEnd)
}
}

struct query_parameter
{
query_parameter(std::string name = {}, std::string value = {})
: name(std::move(name)), value(std::move(value)) {}

std::string name;
std::string value;
};

// Standard logger class used by default.
class standard_logger_impl : public logger_impl
{
Expand All @@ -43,8 +52,16 @@ class standard_logger_impl : public logger_impl
}

lastQuery_ = query;
reset_query_parameter();
}

virtual void add_query_parameter(std::string name, std::string value)
{
queryParams_.emplace_back(std::move(name), std::move(value));
}

virtual void reset_query_parameter() { queryParams_.clear(); }

virtual void set_stream(std::ostream * s)
{
logStream_ = s;
Expand All @@ -60,6 +77,31 @@ class standard_logger_impl : public logger_impl
return lastQuery_;
}

virtual std::string get_last_query_with_context() const
{
if (queryParams_.empty()) {
return get_last_query();
}

std::string query = get_last_query();

query += " with ";

for (std::size_t i = 0; i < queryParams_.size(); ++i)
{
const query_parameter &param = queryParams_[i];

query += ":" + param.name + "=" + param.value;

if (i + 1 < queryParams_.size())
{
query += ", ";
}
}

return query;
}

private:
virtual logger_impl* do_clone() const
{
Expand All @@ -68,6 +110,7 @@ class standard_logger_impl : public logger_impl

std::ostream * logStream_;
std::string lastQuery_;
std::vector<query_parameter> queryParams_;
};

} // namespace anonymous
Expand Down Expand Up @@ -449,6 +492,30 @@ void session::log_query(std::string const & query)
}
}

void session::reset_query_parameter()
{
if (isFromPool_)
{
pool_->at(poolPosition_).reset_query_parameter();
}
else
{
logger_.reset_query_parameter();
}
}

void session::add_query_parameter(std::string name, std::string value)
{
if (isFromPool_)
{
pool_->at(poolPosition_).add_query_parameter(std::move(name), std::move(value));
}
else
{
logger_.add_query_parameter(std::move(name), std::move(value));
}
}

std::string session::get_last_query() const
{
if (isFromPool_)
Expand All @@ -461,6 +528,18 @@ std::string session::get_last_query() const
}
}

std::string session::get_last_query_with_context() const
{
if (isFromPool_)
{
return pool_->at(poolPosition_).get_last_query_with_context();
}
else
{
return logger_.get_last_query_with_context();
}
}

void session::set_got_data(bool gotData)
{
if (isFromPool_)
Expand Down
36 changes: 24 additions & 12 deletions src/core/statement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,27 @@
#include <ctime>
#include <cctype>
#include <cstdint>
#include <string>
#include <sstream>

using namespace soci;
using namespace soci::details;


std::string get_name(const details::use_type_base &param, std::size_t position,
const statement_backend *backend)
{
// Use the name specified in the "use()" call if any,
// otherwise get the name of the matching parameter from
// the query itself, as parsed by the backend.
std::string name = param.get_name();
if (backend && name.empty())
name = backend->get_parameter_name(static_cast<int>(position));

return name.empty() ? std::to_string(position + 1) : name;
}


statement_impl::statement_impl(session & s)
: session_(s), refCount_(1), row_(0),
fetchSize_(1), initialFetchSize_(1),
Expand Down Expand Up @@ -574,10 +590,17 @@ void statement_impl::pre_fetch()

void statement_impl::pre_use()
{
session_.reset_query_parameter();

std::size_t const usize = uses_.size();
for (std::size_t i = 0; i != usize; ++i)
{
uses_[i]->pre_use();

std::string name = get_name(*uses_[i], i, backEnd_);
std::stringstream value;
uses_[i]->dump_value(value);
session_.add_query_parameter(std::move(name), value.str());
}
}

Expand Down Expand Up @@ -854,20 +877,9 @@ statement_impl::rethrow_current_exception_with_context(char const* operation)

details::use_type_base const& u = *uses_[i];

// Use the name specified in the "use()" call if any,
// otherwise get the name of the matching parameter from
// the query itself, as parsed by the backend.
std::string name = u.get_name();
if (name.empty())
name = backEnd_->get_parameter_name(static_cast<int>(i));
oss << ":" << get_name(u, i, backEnd_);

oss << ":";
if (!name.empty())
oss << name;
else
oss << (i + 1);
oss << "=";

u.dump_value(oss);
}
}
Expand Down
12 changes: 10 additions & 2 deletions tests/common-tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -3640,16 +3640,20 @@ TEST_CASE_METHOD(common_tests, "Basic logging support", "[core][logging]")
catch (...) {}

CHECK(sql.get_last_query() == "drop table soci_test1");
CHECK(sql.get_last_query() == sql.get_last_query_with_context());

sql.set_log_stream(NULL);

try
{
sql << "drop table soci_test2";
int val1 = 1;
std::string val2 = "b";
sql << "insert into soci_test2 (a,b) values (:first,:second)", use(val1), use(val2);
}
catch (...) {}

CHECK(sql.get_last_query() == "drop table soci_test2");
CHECK(sql.get_last_query() == "insert into soci_test2 (a,b) values (:first,:second)");
CHECK(sql.get_last_query() == "insert into soci_test2 (a,b) values (:first,:second) with :first=1, :second=\"b\"");

sql.set_log_stream(&log);

Expand Down Expand Up @@ -6974,6 +6978,10 @@ TEST_CASE_METHOD(common_tests, "Logger", "[core][log]")
m_logbuf.push_back(query);
}

virtual void reset_query_parameter() {}

virtual void add_query_parameter(std::string /*name*/, std::string /*value*/) {}

private:
virtual logger_impl* do_clone() const
{
Expand Down

0 comments on commit b148409

Please sign in to comment.