Commit 2f8a7a05 authored by Maciej Sobczak's avatar Maciej Sobczak

Added bulk iterators for Oracle and PostgreSQL.

parent 2fcad8b2
//
// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
// Copyright (C) 2004-2016 Maciej Sobczak, Stephen Hutton
// 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)
......@@ -83,18 +83,30 @@ class SOCI_DECL vector_into_type : public into_type_base
{
public:
vector_into_type(void * data, exchange_type type)
: data_(data), type_(type), indVec_(NULL), backEnd_(NULL) {}
: data_(data), type_(type), indVec_(NULL),
begin_(0), end_(NULL), backEnd_(NULL) {}
vector_into_type(void * data, exchange_type type,
std::size_t begin, std::size_t * end)
: data_(data), type_(type), indVec_(NULL),
begin_(begin), end_(end), backEnd_(NULL) {}
vector_into_type(void * data, exchange_type type,
std::vector<indicator> & ind)
: data_(data), type_(type), indVec_(&ind), backEnd_(NULL) {}
: data_(data), type_(type), indVec_(&ind),
begin_(0), end_(NULL), backEnd_(NULL) {}
vector_into_type(void * data, exchange_type type,
std::vector<indicator> & ind,
std::size_t begin, std::size_t * end)
: data_(data), type_(type), indVec_(&ind),
begin_(begin), end_(end), backEnd_(NULL) {}
~vector_into_type();
protected:
virtual void post_fetch(bool gotData, bool calledFromFetch);
private:
virtual void define(statement_impl & st, int & position);
virtual void pre_fetch();
virtual void clean_up();
......@@ -104,6 +116,8 @@ private:
void * data_;
exchange_type type_;
std::vector<indicator> * indVec_;
std::size_t begin_;
std::size_t * end_;
vector_into_type_backend * backEnd_;
......@@ -132,9 +146,21 @@ public:
into_type(std::vector<T> & v)
: vector_into_type(&v,
static_cast<exchange_type>(exchange_traits<T>::x_type)) {}
into_type(std::vector<T> & v, std::size_t begin, std::size_t * end)
: vector_into_type(&v,
static_cast<exchange_type>(exchange_traits<T>::x_type),
begin, end) {}
into_type(std::vector<T> & v, std::vector<indicator> & ind)
: vector_into_type(&v,
static_cast<exchange_type>(exchange_traits<T>::x_type), ind) {}
into_type(std::vector<T> & v, std::vector<indicator> & ind,
std::size_t begin, std::size_t * end)
: vector_into_type(&v,
static_cast<exchange_type>(exchange_traits<T>::x_type), ind,
begin, end) {}
};
// helper dispatchers for basic types
......@@ -157,6 +183,20 @@ into_type_ptr do_into(T & t, std::vector<indicator> & ind, basic_type_tag)
return into_type_ptr(new into_type<T>(t, ind));
}
template <typename T>
into_type_ptr do_into(std::vector<T> & t,
std::size_t begin, std::size_t * end, basic_type_tag)
{
return into_type_ptr(new into_type<std::vector<T> >(t, begin, end));
}
template <typename T>
into_type_ptr do_into(std::vector<T> & t, std::vector<indicator> & ind,
std::size_t begin, std::size_t * end, basic_type_tag)
{
return into_type_ptr(new into_type<std::vector<T> >(t, ind, begin, end));
}
} // namespace details
} // namespace soci
......
//
// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
// Copyright (C) 2004-2016 Maciej Sobczak, Stephen Hutton
// 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)
......@@ -67,6 +67,24 @@ details::into_type_ptr into(T & t, std::size_t bufSize)
return details::into_type_ptr(new details::into_type<T>(t, bufSize));
}
// vectors with index ranges
template <typename T>
details::into_type_ptr into(std::vector<T> & t,
std::size_t begin, std::size_t & end)
{
return details::do_into(t, begin, &end,
typename details::exchange_traits<std::vector<T> >::type_family());
}
template <typename T>
details::into_type_ptr into(std::vector<T> & t, std::vector<indicator> & ind,
std::size_t begin, std::size_t & end)
{
return details::do_into(t, ind, begin, &end,
typename details::exchange_traits<std::vector<T> >::type_family());
}
} // namespace soci
#endif // SOCI_INTO_H_INCLUDED
......@@ -41,6 +41,8 @@ public:
}
once_temp_type & operator,(into_type_ptr const &);
once_temp_type & operator,(use_type_ptr const &);
template <typename T, typename Indicator>
once_temp_type &operator,(into_container<T, Indicator> const &ic)
{
......
......@@ -79,16 +79,25 @@ struct oracle_vector_into_type_backend : details::vector_into_type_backend
{
oracle_vector_into_type_backend(oracle_statement_backend &st)
: statement_(st), defnp_(NULL), indOCIHolders_(NULL),
data_(NULL), buf_(NULL) {}
data_(NULL), buf_(NULL), user_ranges_(true) {}
virtual void define_by_pos(int &position,
void *data, details::exchange_type type);
void *data, details::exchange_type type)
{
user_ranges_ = false;
define_by_pos(position, data, type, 0, &end_var_);
}
virtual void define_by_pos(
int & position, void * data, details::exchange_type type,
std::size_t begin, std::size_t * end);
virtual void pre_fetch();
virtual void post_fetch(bool gotData, indicator *ind);
virtual void resize(std::size_t sz);
virtual std::size_t size();
std::size_t full_size();
virtual void clean_up();
......@@ -104,6 +113,10 @@ struct oracle_vector_into_type_backend : details::vector_into_type_backend
void *data_;
char *buf_; // generic buffer
details::exchange_type type_;
std::size_t begin_;
std::size_t * end_;
std::size_t end_var_;
bool user_ranges_;
std::size_t colSize_; // size of the string column (used for strings)
std::vector<ub2> sizes_; // sizes of data fetched (used for strings)
......@@ -145,10 +158,25 @@ struct oracle_vector_use_type_backend : details::vector_use_type_backend
: statement_(st), bindp_(NULL), indOCIHolders_(NULL),
data_(NULL), buf_(NULL) {}
virtual void bind_by_pos(int &position,
void *data, details::exchange_type type);
virtual void bind_by_pos(int & position,
void * data, details::exchange_type type)
{
bind_by_pos(position, data, type, 0, &end_var_);
}
virtual void bind_by_pos(int & position,
void * data, details::exchange_type type,
std::size_t begin, std::size_t * end);
virtual void bind_by_name(const std::string & name,
void * data, details::exchange_type type)
{
bind_by_name(name, data, type, 0, &end_var_);
}
virtual void bind_by_name(std::string const &name,
void *data, details::exchange_type type);
void *data, details::exchange_type type,
std::size_t begin, std::size_t * end);
// common part for bind_by_pos and bind_by_name
void prepare_for_bind(void *&data, sb4 &size, ub2 &oracleType);
......@@ -159,7 +187,8 @@ struct oracle_vector_use_type_backend : details::vector_use_type_backend
virtual void pre_use(indicator const *ind);
virtual std::size_t size();
virtual std::size_t size(); // active size (might be lower than full vector size)
std::size_t full_size(); // actual size of the user-provided vector
virtual void clean_up();
......@@ -171,6 +200,9 @@ struct oracle_vector_use_type_backend : details::vector_use_type_backend
void *data_;
char *buf_; // generic buffer
details::exchange_type type_;
std::size_t begin_;
std::size_t * end_;
std::size_t end_var_;
// used for strings only
std::vector<ub2> sizes_;
......
......@@ -149,16 +149,25 @@ struct postgresql_standard_into_type_backend : details::standard_into_type_backe
struct postgresql_vector_into_type_backend : details::vector_into_type_backend
{
postgresql_vector_into_type_backend(postgresql_statement_backend & st)
: statement_(st) {}
: statement_(st), user_ranges_(true) {}
virtual void define_by_pos(int & position,
void * data, details::exchange_type type);
void * data, details::exchange_type type)
{
user_ranges_ = false;
define_by_pos(position, data, type, 0, &end_var_);
}
virtual void define_by_pos(int & position,
void * data, details::exchange_type type,
std::size_t begin, std::size_t * end);
virtual void pre_fetch();
virtual void post_fetch(bool gotData, indicator * ind);
virtual void resize(std::size_t sz);
virtual std::size_t size();
virtual std::size_t size(); // active size (might be lower than full vector size)
std::size_t full_size(); // actual size of the user-provided vector
virtual void clean_up();
......@@ -166,6 +175,10 @@ struct postgresql_vector_into_type_backend : details::vector_into_type_backend
void * data_;
details::exchange_type type_;
std::size_t begin_;
std::size_t * end_;
std::size_t end_var_;
bool user_ranges_;
int position_;
};
......@@ -199,13 +212,29 @@ struct postgresql_vector_use_type_backend : details::vector_use_type_backend
: statement_(st), position_(0) {}
virtual void bind_by_pos(int & position,
void * data, details::exchange_type type);
void * data, details::exchange_type type)
{
bind_by_pos(position, data, type, 0, &end_var_);
}
virtual void bind_by_pos(int & position,
void * data, details::exchange_type type,
std::size_t begin, std::size_t * end);
virtual void bind_by_name(std::string const & name,
void * data, details::exchange_type type);
void * data, details::exchange_type type)
{
bind_by_name(name, data, type, 0, &end_var_);
}
virtual void bind_by_name(const std::string & name,
void * data, details::exchange_type type,
std::size_t begin, std::size_t * end);
virtual void pre_use(indicator const * ind);
virtual std::size_t size();
virtual std::size_t size(); // active size (might be lower than full vector size)
std::size_t full_size(); // actual size of the user-provided vector
virtual void clean_up();
......@@ -213,6 +242,9 @@ struct postgresql_vector_use_type_backend : details::vector_use_type_backend
void * data_;
details::exchange_type type_;
std::size_t begin_;
std::size_t * end_;
std::size_t end_var_;
int position_;
std::string name_;
std::vector<char *> buffers_;
......
......@@ -83,6 +83,13 @@ public:
vector_into_type_backend() {}
virtual ~vector_into_type_backend() {}
virtual void define_by_pos(
int & /* position */, void * /* data */, exchange_type /* type */,
std::size_t /* begin */, std::size_t * /* end */)
{
throw soci_error("into bulk iterators are not supported with this backend");
}
virtual void define_by_pos(int& position, void* data, exchange_type type) = 0;
virtual void pre_fetch() = 0;
......@@ -126,9 +133,22 @@ public:
virtual ~vector_use_type_backend() {}
virtual void bind_by_pos(int& position, void* data, exchange_type type) = 0;
virtual void bind_by_pos(int& /* position */, void* /* data */, exchange_type /* type */,
std::size_t /* begin */, std::size_t * /* end */)
{
throw soci_error("use bulk iterators are not supported with this backend");
}
virtual void bind_by_name(std::string const& name,
void* data, exchange_type type) = 0;
virtual void bind_by_name(std::string const& /* name */,
void* /* data */, exchange_type /* type */,
std::size_t /* begin */, std::size_t * /* end */)
{
throw soci_error("use bulk iterators are not supported with this backend");
}
virtual void pre_use(indicator const* ind) = 0;
virtual std::size_t size() = 0;
......
//
// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
// Copyright (C) 2004-2016 Maciej Sobczak, Stephen Hutton
// 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)
......@@ -190,21 +190,32 @@ public:
typename type_conversion<T>::base_type
> base_type;
conversion_into_type(std::vector<T> & value)
: details::base_vector_holder<T>(value.size())
, into_type<base_type>(details::base_vector_holder<T>::vec_, ownInd_)
, value_(value)
, ownInd_()
, ind_(ownInd_)
conversion_into_type(std::vector<T> & value,
std::size_t begin, std::size_t * end)
: details::base_vector_holder<T>(value.size()),
into_type<base_type>(
details::base_vector_holder<T>::vec_, ownInd_, begin, end),
value_(value),
ownInd_(),
ind_(ownInd_),
begin_(begin),
end_(end)
{
user_ranges_ = end != NULL;
}
conversion_into_type(std::vector<T> & value, std::vector<indicator> & ind)
: details::base_vector_holder<T>(value.size())
, into_type<base_type>(details::base_vector_holder<T>::vec_, ind)
, value_(value)
, ind_(ind)
{}
conversion_into_type(std::vector<T> & value, std::vector<indicator> & ind,
std::size_t begin, std::size_t * end)
: details::base_vector_holder<T>(value.size()),
into_type<base_type>(
details::base_vector_holder<T>::vec_, ind, begin, end),
value_(value),
ind_(ind),
begin_(begin),
end_(end)
{
user_ranges_ = end != NULL;
}
virtual std::size_t size() const
{
......@@ -213,25 +224,39 @@ public:
std::size_t const userSize = value_.size();
details::base_vector_holder<T>::vec_.resize(userSize);
return userSize;
return into_type<base_type>::size();
}
virtual void resize(std::size_t sz)
{
value_.resize(sz);
ind_.resize(sz);
details::base_vector_holder<T>::vec_.resize(sz);
into_type<base_type>::resize(sz);
std::size_t actual_size = details::base_vector_holder<T>::vec_.size();
value_.resize(actual_size);
ind_.resize(actual_size);
}
private:
void convert_from_base()
{
std::size_t const sz = details::base_vector_holder<T>::vec_.size();
for (std::size_t i = 0; i != sz; ++i)
if (user_ranges_)
{
type_conversion<T>::from_base(
details::base_vector_holder<T>::vec_[i], ind_[i], value_[i]);
for (std::size_t i = begin_; i != *end_; ++i)
{
type_conversion<T>::from_base(
details::base_vector_holder<T>::vec_[i], ind_[i], value_[i]);
}
}
else
{
std::size_t const sz = details::base_vector_holder<T>::vec_.size();
for (std::size_t i = 0; i != sz; ++i)
{
type_conversion<T>::from_base(
details::base_vector_holder<T>::vec_[i], ind_[i], value_[i]);
}
}
}
......@@ -244,6 +269,10 @@ private:
// and can be used by conversion routines
std::vector<indicator> & ind_;
std::size_t begin_;
std::size_t * end_;
bool user_ranges_;
SOCI_NOT_COPYABLE(conversion_into_type)
};
......@@ -262,25 +291,34 @@ public:
> base_type;
conversion_use_type(std::vector<T> & value,
std::string const & name=std::string())
: details::base_vector_holder<T>(value.size())
, use_type<base_type>(
details::base_vector_holder<T>::vec_, ownInd_, name)
, value_(value)
, ownInd_()
, ind_(ownInd_)
std::size_t begin, std::size_t * end,
std::string const & name=std::string())
: details::base_vector_holder<T>(value.size()),
use_type<base_type>(
details::base_vector_holder<T>::vec_, ownInd_, begin, end, name),
value_(value),
ownInd_(),
ind_(ownInd_),
begin_(begin),
end_(end)
{
user_ranges_ = end != NULL;
}
conversion_use_type(std::vector<T> & value,
std::vector<indicator> & ind,
std::string const & name = std::string())
: details::base_vector_holder<T>(value.size())
, use_type<base_type>(
details::base_vector_holder<T>::vec_, ind, name)
, value_(value)
, ind_(ind)
{}
std::vector<indicator> & ind,
std::size_t begin, std::size_t * end,
std::string const & name = std::string())
: details::base_vector_holder<T>(value.size()),
use_type<base_type>(
details::base_vector_holder<T>::vec_, ind, begin, end, name),
value_(value),
ind_(ind),
begin_(begin),
end_(end)
{
user_ranges_ = end != NULL;
}
private:
void convert_from_base()
......@@ -288,10 +326,22 @@ private:
std::size_t const sz = details::base_vector_holder<T>::vec_.size();
value_.resize(sz);
ind_.resize(sz);
for (std::size_t i = 0; i != sz; ++i)
if (user_ranges_)
{
type_conversion<T>::from_base(
details::base_vector_holder<T>::vec_[i], value_[i], ind_[i]);
for (std::size_t i = begin_; i != *end_; ++i)
{
type_conversion<T>::from_base(
details::base_vector_holder<T>::vec_[i], value_[i], ind_[i]);
}
}
else
{
for (std::size_t i = 0; i != sz; ++i)
{
type_conversion<T>::from_base(
details::base_vector_holder<T>::vec_[i], value_[i], ind_[i]);
}
}
}
......@@ -300,10 +350,22 @@ private:
std::size_t const sz = value_.size();
details::base_vector_holder<T>::vec_.resize(sz);
ind_.resize(sz);
for (std::size_t i = 0; i != sz; ++i)
if (user_ranges_)
{
for (std::size_t i = begin_; i != *end_; ++i)
{
type_conversion<T>::to_base(value_[i],
details::base_vector_holder<T>::vec_[i], ind_[i]);
}
}
else
{
type_conversion<T>::to_base(value_[i],
details::base_vector_holder<T>::vec_[i], ind_[i]);
for (std::size_t i = 0; i != sz; ++i)
{
type_conversion<T>::to_base(value_[i],
details::base_vector_holder<T>::vec_[i], ind_[i]);
}
}
}
......@@ -316,6 +378,10 @@ private:
// and can be used by conversion routines
std::vector<indicator> & ind_;
std::size_t begin_;
std::size_t * end_;
bool user_ranges_;
SOCI_NOT_COPYABLE(conversion_use_type)
};
......@@ -331,6 +397,22 @@ into_type_ptr do_into(T & t, indicator & ind, user_type_tag)
return into_type_ptr(new conversion_into_type<T>(t, ind));
}
template <typename T>
into_type_ptr do_into(std::vector<T> & t,
std::size_t begin, size_t * end, user_type_tag)
{
return into_type_ptr(
new conversion_into_type<std::vector<T> >(t, begin, end));
}
template <typename T>
into_type_ptr do_into(std::vector<T> & t, std::vector<indicator> & ind,
std::size_t begin, size_t * end, user_type_tag)
{
return into_type_ptr(
new conversion_into_type<std::vector<T> >(t, ind, begin, end));
}
template <typename T>
use_type_ptr do_use(T & t, std::string const & name, user_type_tag)
{
......@@ -357,6 +439,42 @@ use_type_ptr do_use(T const & t, indicator & ind,
return use_type_ptr(new conversion_use_type<T>(t, ind, name));
}
template <typename T>
use_type_ptr do_use(std::vector<T> & t,
std::size_t begin, size_t * end,
std::string const & name, user_type_tag)
{
return use_type_ptr(
new conversion_use_type<std::vector<T> >(t, begin, end, name));
}
template <typename T>
use_type_ptr do_use(const std::vector<T> & t,
std::size_t begin, size_t * end,
std::string const & name, user_type_tag)
{
return use_type_ptr(
new conversion_use_type<std::vector<T> >(t, begin, end, name));
}
template <typename T>
use_type_ptr do_use(std::vector<T> & t, std::vector<indicator> & ind,
std::size_t begin, size_t * end,
std::string const & name, user_type_tag)
{
return use_type_ptr(
new conversion_use_type<std::vector<T> >(t, ind, begin, end, name));
}
template <typename T>
use_type_ptr do_use(const std::vector<T> & t, std::vector<indicator> & ind,
std::size_t begin, size_t * end,
std::string const & name, user_type_tag)
{
return use_type_ptr(
new conversion_use_type<std::vector<T> >(t, ind, begin, end, name));
}
} // namespace details
} // namespace soci
......
//
// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
// Copyright (C) 2004-2016 Maciej Sobczak, Stephen Hutton
// 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)
......@@ -107,16 +107,45 @@ public:
: data_(data)
, type_(type)
, ind_(NULL)
, begin_(0)
, end_(NULL)
, name_(name)
, backEnd_(NULL)
{}
vector_use_type(void* data, exchange_type type,
std::size_t begin, std::size_t * end,
std::string const& name = std::string())
: data_(data)
, type_(type)
, ind_(NULL)
, begin_(begin)
, end_(end)
, name_(name)
, backEnd_(NULL)
{}
vector_use_type(void* data, exchange_type type,
std::vector<indicator> const& ind,
std::string const& name = std::string())
: data_(data)
, type_(type)
, ind_(&ind)
, begin_(0)
, end_(NULL)
, name_(name)
, backEnd_(NULL)
{}
vector_use_type(void* data, exchange_type type,
std::vector<indicator> const& ind,
std::size_t begin, std::size_t * end,
std::string const& name = std::string())
: data_(data)
, type_(type)
, ind_(&ind)
, begin_(begin)
, end_(end)
, name_(name)
, backEnd_(NULL)
{}
......@@ -135,6 +164,8 @@ private:
void* data_;
exchange_type type_;
std::vector<indicator> const* ind_;
std::size_t begin_;
std::size_t * end_;
std::string name_;
vector_use_type_backend * backEnd_;
......@@ -179,22 +210,46 @@ public:
static_cast<exchange_type>(exchange_traits<T>::x_type), name)
{}
use_type(std::vector<T>& v, std::size_t begin, std::size_t * end,
std::string const& name = std::string())
: vector_use_type(&v,
static_cast<exchange_type>(exchange_traits<T>::x_type), begin, end, name)
{}
use_type(std::vector<T> const& v, std::string const& name = std::string())
: vector_use_type(const_cast<std::vector<T>*>(&v),
static_cast<exchange_type>(exchange_traits<T>::x_type), name)
{}
use_type(std::vector<T> const& v, std::size_t begin, std::size_t * end,
std::string const& name = std::string())
: vector_use_type(const_cast<std::vector<T>*>(&v),
static_cast<exchange_type>(exchange_traits<T>::x_type), begin, end, name)
{}
use_type(std::vector<T>& v, std::vector<indicator> const& ind,
std::string const& name = std::string())
: vector_use_type(&v,
static_cast<exchange_type>(exchange_traits<T>::x_type), ind, name)
{}