Commit b70a4e8b authored by Maciej Sobczak's avatar Maciej Sobczak

Added singlerows mode for PostgreSQL.

parent 596c6762
......@@ -60,6 +60,20 @@ To establish a connection to the PostgreSQL database, create a `session` object
The set of parameters used in the connection string for PostgreSQL is the same as accepted by the `[PQconnectdb](http://www.postgresql.org/docs/8.3/interactive/libpq.html#LIBPQ-CONNECT)` function from the `libpq` library.
In addition to standard PostgreSQL connection parameters, the following can be set:
* `singlerow` or `singlerows`
For example:
session sql(postgresql, "dbname=mydatabase singlerows=true");
If the `singlerows` parameter is set to `true` or `yes`, then queries will be executed in the single-row mode, which prevents the client library from loading full query result set into memory and instead fetches rows one by one, as they are requested by the statement's fetch() function. This mode can be of interest to those users who want to make their client applications more responsive (with more fine-grained operation) by avoiding potentially long blocking times when complete query results are loaded to client's memory.
Note that in the single-row operation:
* bulk queries are not supported, and
* in order to fulfill the expectations of the underlying client library, the complete rowset has to be exhausted before executing further queries on the same session.
Once you have created a `session` object as shown above, you can use it to access the database, for example:
int count;
......
......@@ -32,6 +32,7 @@ public:
// Retrieve the backend and the connection strings specified in the ctor.
backend_factory const * get_factory() const { return factory_; }
void set_connect_string(const std::string & connectString) { connectString_ = connectString; }
std::string const & get_connect_string() const { return connectString_; }
// Set the value of the given option, overwriting any previous value.
......
......@@ -215,7 +215,8 @@ struct postgresql_vector_use_type_backend : details::vector_use_type_backend
struct postgresql_session_backend;
struct postgresql_statement_backend : details::statement_backend
{
postgresql_statement_backend(postgresql_session_backend & session);
postgresql_statement_backend(postgresql_session_backend & session,
bool single_row_mode);
~postgresql_statement_backend();
virtual void alloc();
......@@ -243,6 +244,8 @@ struct postgresql_statement_backend : details::statement_backend
postgresql_session_backend & session_;
bool single_row_mode_;
details::postgresql_result result_;
std::string query_;
details::statement_type stType_;
......@@ -304,7 +307,8 @@ struct postgresql_blob_backend : details::blob_backend
struct postgresql_session_backend : details::session_backend
{
postgresql_session_backend(connection_parameters const & parameters);
postgresql_session_backend(connection_parameters const & parameters,
bool single_row_mode);
~postgresql_session_backend();
......@@ -328,6 +332,7 @@ struct postgresql_session_backend : details::session_backend
std::string get_next_statement_name();
int statementCount_;
bool single_row_mode_;
PGconn * conn_;
};
......
......@@ -7,6 +7,7 @@
#define SOCI_POSTGRESQL_SOURCE
#include "soci/postgresql/soci-postgresql.h"
#include "soci/connection-parameters.h"
#include "soci/backend-loader.h"
#include <libpq/libpq-fs.h> // libpq
......@@ -23,11 +24,103 @@
using namespace soci;
using namespace soci::details;
namespace // unnamed
{
// iterates the string pointed by i, searching for pairs of key value.
// it returns the position after the value
std::string::const_iterator get_key_value(std::string::const_iterator & i,
std::string::const_iterator const & end,
std::string & key,
std::string & value)
{
bool in_value = false;
bool quoted = false;
key.clear();
value.clear();
while (i != end)
{
if (in_value == false)
{
if (*i == '=')
{
in_value = true;
if (i != end && *(i + 1) == '"')
{
quoted = true;
++i; // jump over the quote
}
}
else if (!isspace(*i))
{
key += *i;
}
}
else
{
if ((quoted == true && *i == '"') || (quoted == false && isspace(*i)))
{
return ++i;
}
else
{
value += *i;
}
}
++i;
}
return i;
}
// retrieves specific parameters from the
// uniform connect string
std::string chop_connect_string(std::string const & connectString,
bool & single_row_mode)
{
std::string pruned_conn_string;
single_row_mode = false;
std::string key, value;
std::string::const_iterator i = connectString.begin();
while (i != connectString.end())
{
i = get_key_value(i, connectString.end(), key, value);
if (key == "singlerow" || key == "singlerows")
{
single_row_mode = (value == "true" || value == "yes");
}
else
{
if (pruned_conn_string.empty() == false)
{
pruned_conn_string += ' ';
}
pruned_conn_string += key + '=' + value;
}
}
return pruned_conn_string;
}
} // unnamed namespace
// concrete factory for Empty concrete strategies
postgresql_session_backend * postgresql_backend_factory::make_session(
connection_parameters const & parameters) const
{
return new postgresql_session_backend(parameters);
bool single_row_mode;
const std::string pruned_conn_string =
chop_connect_string(parameters.get_connect_string(), single_row_mode);
connection_parameters pruned_parameters(parameters);
pruned_parameters.set_connect_string(pruned_conn_string);
return new postgresql_session_backend(pruned_parameters, single_row_mode);
}
postgresql_backend_factory const soci::postgresql;
......
......@@ -38,7 +38,7 @@ void hard_exec(PGconn * conn, char const * query, char const * errMsg)
} // namespace unnamed
postgresql_session_backend::postgresql_session_backend(
connection_parameters const& parameters)
connection_parameters const& parameters, bool single_row_mode)
: statementCount_(0)
{
PGconn* conn = PQconnectdb(parameters.get_connect_string().c_str());
......@@ -65,6 +65,8 @@ postgresql_session_backend::postgresql_session_backend(
: "SET extra_float_digits = 2",
"Cannot set extra_float_digits parameter");
single_row_mode_ = single_row_mode;
conn_ = conn;
}
......@@ -123,7 +125,7 @@ std::string postgresql_session_backend::get_next_statement_name()
postgresql_statement_backend * postgresql_session_backend::make_statement_backend()
{
return new postgresql_statement_backend(*this);
return new postgresql_statement_backend(*this, single_row_mode_);
}
postgresql_rowid_backend * postgresql_session_backend::make_rowid_backend()
......
This diff is collapsed.
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