Skip to content

Commit

Permalink
add support of bulk operations for ORM in ORACLE and SQLite backends.
Browse files Browse the repository at this point in the history
  • Loading branch information
vyskubov committed Jun 2, 2023
1 parent a4fb0b0 commit 18657fa
Show file tree
Hide file tree
Showing 15 changed files with 626 additions and 86 deletions.
41 changes: 30 additions & 11 deletions include/soci/row.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@

namespace soci
{
struct CaseInsensitiveComparator {
bool operator()(const std::string& a, const std::string& b) const noexcept
{
return ::strcasecmp(a.c_str(), b.c_str()) < 0;
}
};

class SOCI_DECL column_properties
{
Expand All @@ -40,7 +46,7 @@ class SOCI_DECL column_properties
class SOCI_DECL row
{
public:
row();
row(std::size_t bulk_size = 1);
~row();

row(row &&other) = default;
Expand All @@ -51,13 +57,17 @@ class SOCI_DECL row
std::size_t size() const;
void clean_up();

//bulk buffer size
std::size_t bulk_size() const { return bulk_size_; }
void bulk_size(const std::size_t sz) { bulk_size_ = sz; }

indicator get_indicator(std::size_t pos) const;
indicator get_indicator(std::string const& name) const;

template <typename T>
inline void add_holder(T* t, indicator* ind)
inline void add_holder(std::vector<T>* t, std::vector<indicator>* ind)
{
holders_.push_back(new details::type_holder<T>(t));
holders_.push_back(new details::vector_type_holder<T>(t));
indicators_.push_back(ind);
}

Expand All @@ -68,17 +78,17 @@ class SOCI_DECL row
T get(std::size_t pos) const
{
typedef typename type_conversion<T>::base_type base_type;
base_type const& baseVal = holders_.at(pos)->get<base_type>();
base_type const& baseVal = holders_.at(pos)->get<base_type>(bulk_pos_);

T ret;
type_conversion<T>::from_base(baseVal, *indicators_.at(pos), ret);
type_conversion<T>::from_base(baseVal, (*indicators_.at(pos))[bulk_pos_], ret);
return ret;
}

template <typename T>
T get(std::size_t pos, T const &nullValue) const
{
if (i_null == *indicators_.at(pos))
if (i_null == (*indicators_.at(pos))[bulk_pos_])
{
return nullValue;
}
Expand All @@ -98,7 +108,7 @@ class SOCI_DECL row
{
std::size_t const pos = find_column(name);

if (i_null == *indicators_[pos])
if (i_null == (*indicators_[pos])[bulk_pos_])
{
return nullValue;
}
Expand All @@ -122,6 +132,13 @@ class SOCI_DECL row
void reset_get_counter() const
{
currentPos_ = 0;
bulk_pos_ = 0;
}

void next(std::size_t num = 1) const
{
currentPos_ = 0;
bulk_pos_ += num;
}

private:
Expand All @@ -130,12 +147,14 @@ class SOCI_DECL row
std::size_t find_column(std::string const& name) const;

std::vector<column_properties> columns_;
std::vector<details::holder*> holders_;
std::vector<indicator*> indicators_;
std::map<std::string, std::size_t> index_;
std::vector<details::vector_holder*> holders_;
std::vector<std::vector<indicator>*> indicators_;
std::map<std::string, std::size_t, CaseInsensitiveComparator> index_;

bool uppercaseColumnNames_;
mutable std::size_t currentPos_;
mutable std::size_t currentPos_; //column
mutable std::size_t bulk_pos_; //row
mutable std::size_t bulk_size_;
};

} // namespace soci
Expand Down
2 changes: 2 additions & 0 deletions include/soci/soci-platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ namespace std {
}
}
#endif // _MSC_VER < 1800
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#endif // _MSC_VER

#if defined(__CYGWIN__) || defined(__MINGW32__)
Expand Down
5 changes: 5 additions & 0 deletions include/soci/sqlite3/soci-sqlite3.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ struct sqlite3_standard_into_type_backend : details::standard_into_type_backend
int position_;
};

struct sqlite3_column;
struct sqlite3_vector_into_type_backend : details::vector_into_type_backend
{
sqlite3_vector_into_type_backend(sqlite3_statement_backend &st)
Expand All @@ -106,6 +107,10 @@ struct sqlite3_vector_into_type_backend : details::vector_into_type_backend
void *data_;
details::exchange_type type_;
int position_;

private:
data_type get_column_type(int colNum);
sqlite3_column get_column(int colNum);
};

struct sqlite3_standard_use_type_backend : details::standard_use_type_backend
Expand Down
5 changes: 3 additions & 2 deletions include/soci/statement.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,9 @@ class SOCI_DECL statement_impl
template<typename T>
void into_row()
{
T * t = new T();
indicator * ind = new indicator(i_ok);
std::size_t bulk_size = row_->bulk_size();
std::vector<T>* t = new std::vector<T>(bulk_size);
std::vector<indicator>* ind = new std::vector<indicator>(bulk_size);
row_->add_holder(t, ind);
exchange_for_row(into(*t, *ind));
}
Expand Down
92 changes: 49 additions & 43 deletions include/soci/type-conversion.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ struct base_value_holder

// Automatically create into_type from a type_conversion

template <typename T>
template <typename T, typename X>
class conversion_into_type
: private base_value_holder<T>,
public into_type<typename type_conversion<T>::base_type>
Expand Down Expand Up @@ -80,7 +80,7 @@ class conversion_into_type

// Automatically create use_type from a type_conversion

template <typename T>
template <typename T, typename X>
class conversion_use_type
: private base_value_holder<T>,
public use_type<typename type_conversion<T>::base_type>
Expand Down Expand Up @@ -195,8 +195,8 @@ struct base_vector_holder

// Automatically create a std::vector based into_type from a type_conversion

template <typename T>
class conversion_into_type<std::vector<T> >
template <typename T, typename X>
class conversion_into_type<std::vector<T> , X>
: private base_vector_holder<T>,
public into_type<std::vector<typename type_conversion<T>::base_type> >
{
Expand Down Expand Up @@ -295,8 +295,8 @@ class conversion_into_type<std::vector<T> >

// Automatically create a std::vector based use_type from a type_conversion

template <typename T>
class conversion_use_type<std::vector<T> >
template <typename T, typename X>
class conversion_use_type<std::vector<T>, X >
: private base_vector_holder<T>,
public use_type<std::vector<typename type_conversion<T>::base_type> >
{
Expand Down Expand Up @@ -408,98 +408,104 @@ class conversion_use_type<std::vector<T> >
template <typename T>
into_type_ptr do_into(T & t, user_type_tag)
{
return into_type_ptr(new conversion_into_type<T>(t));
return into_type_ptr(new conversion_into_type<T, typename type_conversion<T>::base_type>(t));
}

template <typename T>
into_type_ptr do_into(std::vector<T>& t, user_type_tag)
{
return into_type_ptr(new conversion_into_type<std::vector<T>, typename type_conversion<T>::base_type>(t));
}

template <typename T>
into_type_ptr do_into(T & t, indicator & ind, user_type_tag)
into_type_ptr do_into(T& t, indicator& ind, user_type_tag)
{
return into_type_ptr(new conversion_into_type<T>(t, ind));
return into_type_ptr(new conversion_into_type<T, typename type_conversion<T>::base_type>(t, ind));
}

template <typename T>
into_type_ptr do_into(std::vector<T> & t,
std::size_t begin, size_t * end, user_type_tag)
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));
new conversion_into_type<std::vector<T> , typename type_conversion<T>::base_type>(t, begin, end));
}

template <typename T>
into_type_ptr do_into(std::vector<T> & t, std::vector<indicator> & ind,
into_type_ptr do_into(std::vector<T>& t, std::vector<indicator>& ind,
user_type_tag)
{
return into_type_ptr(new conversion_into_type<std::vector<T> >(t, ind));
return into_type_ptr(new conversion_into_type<std::vector<T> , typename type_conversion<T>::base_type>(t, ind));
}

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)
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));
new conversion_into_type<std::vector<T> , typename type_conversion<T>::base_type>(t, ind, begin, end));
}

template <typename T>
use_type_ptr do_use(T & t, std::string const & name, user_type_tag)
use_type_ptr do_use(T& t, std::string const& name, user_type_tag)
{
return use_type_ptr(new conversion_use_type<T>(t, name));
return use_type_ptr(new conversion_use_type<T, typename type_conversion<T>::base_type>(t, name));
}

template <typename T>
use_type_ptr do_use(T const & t, std::string const & name, user_type_tag)
use_type_ptr do_use(T const& t, std::string const& name, user_type_tag)
{
return use_type_ptr(new conversion_use_type<T>(t, name));
return use_type_ptr(new conversion_use_type<T, typename type_conversion<T>::base_type>(t, name));
}

template <typename T>
use_type_ptr do_use(T & t, indicator & ind,
std::string const & name, user_type_tag)
use_type_ptr do_use(T& t, indicator& ind,
std::string const& name, user_type_tag)
{
return use_type_ptr(new conversion_use_type<T>(t, ind, name));
return use_type_ptr(new conversion_use_type<T, typename type_conversion<T>::base_type>(t, ind, name));
}

template <typename T>
use_type_ptr do_use(T const & t, indicator & ind,
std::string const & name, user_type_tag)
use_type_ptr do_use(T const& t, indicator& ind,
std::string const& name, user_type_tag)
{
return use_type_ptr(new conversion_use_type<T>(t, ind, name));
return use_type_ptr(new conversion_use_type<T, typename type_conversion<T>::base_type>(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)
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));
new conversion_use_type<std::vector<T> , typename type_conversion<T>::base_type>(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)
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));
new conversion_use_type<std::vector<T> , typename type_conversion<T>::base_type>(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)
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));
new conversion_use_type<std::vector<T> , typename type_conversion<T>::base_type>(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)
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));
new conversion_use_type<std::vector<T> , typename type_conversion<T>::base_type>(t, ind, begin, end, name));
}

} // namespace details
Expand Down
Loading

0 comments on commit 18657fa

Please sign in to comment.