Merge commit 'caab155a00ca0158dcb16844bea5326e2a2c2562' into dn

This commit is contained in:
Nik Bougalis
2015-08-18 08:47:41 -07:00
386 changed files with 26285 additions and 19140 deletions

View File

@@ -0,0 +1,5 @@
# soci/include/private
Private headers do not define any parts of public interface,
are not installed in user's filesystem.
Private headers only define common features used internally.

View File

@@ -0,0 +1,271 @@
//
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, Rafal Bobrowski
// 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_FIREBIRD_COMMON_H_INCLUDED
#define SOCI_FIREBIRD_COMMON_H_INCLUDED
#include "soci/firebird/soci-firebird.h"
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <limits>
#include <sstream>
#include <iomanip>
#include <string>
#include <vector>
#include <algorithm>
namespace soci
{
namespace details
{
namespace firebird
{
char * allocBuffer(XSQLVAR* var);
void tmEncode(short type, std::tm * src, void * dst);
void tmDecode(short type, void * src, std::tm * dst);
void setTextParam(char const * s, std::size_t size, char * buf_,
XSQLVAR * var);
std::string getTextParam(XSQLVAR const *var);
template <typename IntType>
const char *str2dec(const char * s, IntType &out, short &scale)
{
int sign = 1;
if ('+' == *s)
++s;
else if ('-' == *s)
{
sign = -1;
++s;
}
scale = 0;
bool period = false;
IntType res = 0;
for (out = 0; *s; ++s, out = res)
{
if (*s == '.')
{
if (period)
return s;
period = true;
continue;
}
int d = *s - '0';
if (d < 0 || d > 9)
return s;
res = res * 10 + static_cast<IntType>(d * sign);
if (1 == sign)
{
if (res < out)
return s;
}
else
{
if (res > out)
return s;
}
if (period)
++scale;
}
return s;
}
template <typename T>
inline
T round_for_isc(T value)
{
return value;
}
inline
double round_for_isc(double value)
{
// Unfortunately all the rounding functions are C99 and so are not supported
// by MSVC, so do it manually.
return value < 0 ? value - 0.5 : value + 0.5;
}
//helper template to generate proper code based on compile time type check
template<bool cond> struct cond_to_isc {};
template<> struct cond_to_isc<false>
{
static void checkInteger(short scale, short type)
{
if( scale >= 0 && (type == SQL_SHORT || type == SQL_LONG || type == SQL_INT64) )
throw soci_error("Can't convert non-integral value to integral column type");
}
};
template<> struct cond_to_isc<true>
{
static void checkInteger(short scale,short type) { SOCI_UNUSED(scale) SOCI_UNUSED(type) }
};
template<typename T1>
void to_isc(void * val, XSQLVAR * var, short x_scale = 0)
{
T1 value = *reinterpret_cast<T1*>(val);
short scale = var->sqlscale + x_scale;
short type = var->sqltype & ~1;
long long divisor = 1, multiplier = 1;
cond_to_isc<std::numeric_limits<T1>::is_integer>::checkInteger(scale,type);
for (int i = 0; i > scale; --i)
multiplier *= 10;
for (int i = 0; i < scale; ++i)
divisor *= 10;
switch (type)
{
case SQL_SHORT:
{
short tmp = static_cast<short>(round_for_isc(value*multiplier)/divisor);
std::memcpy(var->sqldata, &tmp, sizeof(short));
}
break;
case SQL_LONG:
{
int tmp = static_cast<int>(round_for_isc(value*multiplier)/divisor);
std::memcpy(var->sqldata, &tmp, sizeof(int));
}
break;
case SQL_INT64:
{
long long tmp = static_cast<long long>(round_for_isc(value*multiplier)/divisor);
std::memcpy(var->sqldata, &tmp, sizeof(long long));
}
break;
case SQL_FLOAT:
{
float sql_value = static_cast<float>(value);
std::memcpy(var->sqldata, &sql_value, sizeof(float));
}
break;
case SQL_DOUBLE:
{
double sql_value = static_cast<double>(value);
std::memcpy(var->sqldata, &sql_value, sizeof(double));
}
break;
default:
throw soci_error("Incorrect data type for numeric conversion");
}
}
template<typename IntType, typename UIntType>
void parse_decimal(void * val, XSQLVAR * var, const char * s)
{
short scale;
UIntType t1;
IntType t2;
if (!*str2dec(s, t1, scale))
std::memcpy(val, &t1, sizeof(t1));
else if (!*str2dec(s, t2, scale))
std::memcpy(val, &t2, sizeof(t2));
else
throw soci_error("Could not parse decimal value.");
to_isc<IntType>(val, var, scale);
}
template<typename IntType>
std::string format_decimal(const void *sqldata, int sqlscale)
{
IntType x = *reinterpret_cast<const IntType *>(sqldata);
std::stringstream out;
out << x;
std::string r = out.str();
if (sqlscale < 0)
{
if (static_cast<int>(r.size()) - (x < 0) <= -sqlscale)
{
r = std::string(size_t(x < 0), '-') +
std::string(-sqlscale - (r.size() - (x < 0)) + 1, '0') +
r.substr(size_t(x < 0), std::string::npos);
}
return r.substr(0, r.size() + sqlscale) + '.' +
r.substr(r.size() + sqlscale, std::string::npos);
}
return r + std::string(sqlscale, '0');
}
template<bool cond> struct cond_from_isc {};
template<> struct cond_from_isc<true> {
static void checkInteger(short scale)
{
std::ostringstream msg;
msg << "Can't convert value with scale " << -scale
<< " to integral type";
throw soci_error(msg.str());
}
};
template<> struct cond_from_isc<false>
{
static void checkInteger(short scale) { SOCI_UNUSED(scale) }
};
template<typename T1>
T1 from_isc(XSQLVAR * var)
{
short scale = var->sqlscale;
T1 tens = 1;
if (scale < 0)
{
cond_from_isc<std::numeric_limits<T1>::is_integer>::checkInteger(scale);
for (int i = 0; i > scale; --i)
{
tens *= 10;
}
}
switch (var->sqltype & ~1)
{
case SQL_SHORT:
return static_cast<T1>(*reinterpret_cast<short*>(var->sqldata)/tens);
case SQL_LONG:
return static_cast<T1>(*reinterpret_cast<int*>(var->sqldata)/tens);
case SQL_INT64:
return static_cast<T1>(*reinterpret_cast<long long*>(var->sqldata)/tens);
case SQL_FLOAT:
return static_cast<T1>(*reinterpret_cast<float*>(var->sqldata));
case SQL_DOUBLE:
return static_cast<T1>(*reinterpret_cast<double*>(var->sqldata));
default:
throw soci_error("Incorrect data type for numeric conversion");
}
}
template <typename T>
std::size_t getVectorSize(void *p)
{
std::vector<T> *v = static_cast<std::vector<T> *>(p);
return v->size();
}
template <typename T>
void resizeVector(void *p, std::size_t sz)
{
std::vector<T> *v = static_cast<std::vector<T> *>(p);
v->resize(sz);
}
} // namespace firebird
} // namespace details
} // namespace soci
#endif // SOCI_FIREBIRD_COMMON_H_INCLUDED

View File

@@ -0,0 +1,35 @@
//
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, Rafal Bobrowski
// 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_FIREBIRD_ERROR_H_INCLUDED
#define SOCI_FIREBIRD_ERROR_H_INCLUDED
#include "soci/firebird/soci-firebird.h"
#include <string>
namespace soci
{
namespace details
{
namespace firebird
{
void SOCI_FIREBIRD_DECL get_iscerror_details(ISC_STATUS * status_vector, std::string &msg);
bool SOCI_FIREBIRD_DECL check_iscerror(ISC_STATUS const * status_vector, long errNum);
void SOCI_FIREBIRD_DECL throw_iscerror(ISC_STATUS * status_vector);
} // namespace firebird
} // namespace details
} // namespace soci
#endif // SOCI_FIREBIRD_ERROR_H_INCLUDED

View File

@@ -0,0 +1,39 @@
//
// Copyright (C) 2015 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_PRIVATE_SOCI_COMPILER_H_INCLUDED
#define SOCI_PRIVATE_SOCI_COMPILER_H_INCLUDED
#include "soci-cpp.h"
// CHECK_GCC(major,minor) evaluates to 1 when using g++ of at least this
// version or 0 when using g++ of lesser version or not using g++ at all.
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
# define CHECK_GCC(major, minor) \
((__GNUC__ > (major)) \
|| (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
#else
# define CHECK_GCC(major, minor) 0
#endif
// GCC_WARNING_{SUPPRESS,RESTORE} macros can be used to bracket the code
// producing a specific warning to disable it.
//
// They only work with g++ 4.6+ or clang, warnings are not disabled for earlier
// g++ versions.
#if defined(__clang__) || CHECK_GCC(4, 6)
# define GCC_WARNING_SUPPRESS(x) \
_Pragma (SOCI_STRINGIZE(GCC diagnostic push)) \
_Pragma (SOCI_STRINGIZE(GCC diagnostic ignored SOCI_STRINGIZE(SOCI_CONCAT(-W,x))))
# define GCC_WARNING_RESTORE(x) \
_Pragma (SOCI_STRINGIZE(GCC diagnostic pop))
#else /* gcc < 4.6 or not gcc and not clang at all */
# define GCC_WARNING_SUPPRESS(x)
# define GCC_WARNING_RESTORE(x)
#endif
#endif // SOCI_PRIVATE_SOCI_COMPILER_H_INCLUDED

View File

@@ -0,0 +1,30 @@
//
// Copyright (C) 2015 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_PRIVATE_SOCI_CPP_H_INCLUDED
#define SOCI_PRIVATE_SOCI_CPP_H_INCLUDED
// Some very common preprocessor helpers.
// SOCI_CONCAT() pastes together two tokens after expanding them.
#define SOCI_CONCAT_IMPL(x, y) x ## y
#define SOCI_CONCAT(x, y) SOCI_CONCAT_IMPL(x, y)
// SOCI_STRINGIZE() makes a string of its argument after expanding it.
#define SOCI_STRINGIZE_IMPL(x) #x
#define SOCI_STRINGIZE(x) SOCI_STRINGIZE_IMPL(x)
// SOCI_MAKE_UNIQUE_NAME() creates a uniquely named identifier with the given
// prefix.
//
// It uses __COUNTER__ macro to avoid problems with broken __LINE__ in MSVC
// when using "Edit and Continue" (/ZI) option as there are no compilers known
// to work with SOCI and not support it. If one such is ever discovered, we
// should use __LINE__ for it instead.
#define SOCI_MAKE_UNIQUE_NAME(name) SOCI_CONCAT(name, __COUNTER__)
#endif // SOCI_PRIVATE_SOCI_CPP_H_INCLUDED

View File

@@ -0,0 +1,80 @@
//
// 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_PRIVATE_SOCI_CSTRTOD_H_INCLUDED
#define SOCI_PRIVATE_SOCI_CSTRTOD_H_INCLUDED
#include "soci/error.h"
#include <stdlib.h>
#include <string.h>
namespace soci
{
namespace details
{
// Locale-independent, i.e. always using "C" locale, function for converting
// strings to numbers.
//
// The string must contain a floating point number in "C" locale, i.e. using
// point as decimal separator, and nothing but it. If it does, the converted
// number is returned, otherwise an exception is thrown.
inline
double cstring_to_double(char const* s)
{
// Unfortunately there is no clean way to parse a number in C locale
// without this hack: normally, using std::istringstream with classic
// locale should work, but some standard library implementations are buggy
// and handle non-default locale in thread-unsafe way, by changing the
// global C locale which is unacceptable as it introduces subtle bugs in
// multi-thread programs. So we rely on just the standard C functions and
// try to make them work by tweaking the input into the form appropriate
// for the current locale.
// First try with the original input.
char* end;
double d = strtod(s, &end);
bool parsedOK;
if (*end == '.')
{
// Parsing may have stopped because the current locale uses something
// different from the point as decimal separator, retry with a comma.
//
// In principle, values other than point or comma are possible but they
// don't seem to be used in practice, so for now keep things simple.
size_t const bufSize = strlen(s) + 1;
char* const buf = new char[bufSize];
strcpy(buf, s);
buf[end - s] = ',';
d = strtod(buf, &end);
parsedOK = end != buf && *end == '\0';
delete [] buf;
}
else
{
// Notice that we must detect false positives as well: parsing a string
// using decimal comma should fail when using this function.
parsedOK = end != s && *end == '\0' && !strchr(s, ',');
}
if (!parsedOK)
{
throw soci_error(std::string("Cannot convert data: string \"") + s + "\" "
"is not a number.");
}
return d;
}
} // namespace details
} // namespace soci
#endif // SOCI_PRIVATE_SOCI_CSTRTOD_H_INCLUDED

View File

@@ -0,0 +1,58 @@
//
// 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_PRIVATE_SOCI_DTOCSTR_H_INCLUDED
#define SOCI_PRIVATE_SOCI_DTOCSTR_H_INCLUDED
#include "soci/soci-platform.h"
#include "soci/error.h"
#include <stdlib.h>
#include <stdio.h>
namespace soci
{
namespace details
{
// Locale-independent, i.e. always using "C" locale, function for converting
// floating point number to string.
//
// The resulting string will contain the floating point number in "C" locale,
// i.e. will always use point as decimal separator independently of the current
// locale.
inline
std::string double_to_cstring(double d)
{
// See comments in cstring_to_double() in soci-cstrtod.h, we're dealing
// with the same issues here.
static size_t const bufSize = 32;
char buf[bufSize];
snprintf(buf, bufSize, "%.20g", d);
// Replace any commas which can be used as decimal separator with points.
for (char* p = buf; *p != '\0'; p++ )
{
if (*p == ',')
{
*p = '.';
// There can be at most one comma in this string anyhow.
break;
}
}
return buf;
}
} // namespace details
} // namespace soci
#endif // SOCI_PRIVATE_SOCI_DTOCSTR_H_INCLUDED

View File

@@ -0,0 +1,84 @@
//
// Copyright (C) 2015 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_EXCHANGE_CAST_H_INCLUDED
#define SOCI_EXCHANGE_CAST_H_INCLUDED
#include "soci/soci-backend.h"
#include <ctime>
namespace soci
{
namespace details
{
// cast the given non-null untyped pointer to its corresponding type
template <exchange_type e> struct exchange_type_traits;
template <>
struct exchange_type_traits<x_char>
{
typedef char value_type;
};
template <>
struct exchange_type_traits<x_stdstring>
{
typedef std::string value_type;
};
template <>
struct exchange_type_traits<x_short>
{
typedef short value_type;
};
template <>
struct exchange_type_traits<x_integer>
{
typedef int value_type;
};
template <>
struct exchange_type_traits<x_long_long>
{
typedef long long value_type;
};
template <>
struct exchange_type_traits<x_unsigned_long_long>
{
typedef unsigned long long value_type;
};
template <>
struct exchange_type_traits<x_double>
{
typedef double value_type;
};
template <>
struct exchange_type_traits<x_stdtm>
{
typedef std::tm value_type;
};
// exchange_type_traits not defined for x_statement, x_rowid and x_blob here.
template <exchange_type e>
typename exchange_type_traits<e>::value_type& exchange_type_cast(void *data)
{
return *static_cast<typename exchange_type_traits<e>::value_type*>(data);
}
} // namespace details
} // namespace soci
#endif // SOCI_EXCHANGE_CAST_H_INCLUDED

View File

@@ -0,0 +1,46 @@
//
// Copyright (C) 2015 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_PRIVATE_SOCI_MKTIME_H_INCLUDED
#define SOCI_PRIVATE_SOCI_MKTIME_H_INCLUDED
// Not <ctime> because we also want to get timegm() if available.
#include <time.h>
namespace soci
{
namespace details
{
// Fill the provided struct tm with the values corresponding to the given date
// in UTC.
//
// Notice that both years and months are normal human 1-based values here and
// not 1900 or 0-based as in struct tm itself.
inline
void
mktime_from_ymdhms(tm& t,
int year, int month, int day,
int hour, int minute, int second)
{
t.tm_isdst = -1;
t.tm_year = year - 1900;
t.tm_mon = month - 1;
t.tm_mday = day;
t.tm_hour = hour;
t.tm_min = minute;
t.tm_sec = second;
mktime(&t);
}
} // namespace details
} // namespace soci
#endif // SOCI_PRIVATE_SOCI_MKTIME_H_INCLUDED

View File

@@ -0,0 +1,19 @@
//
// Copyright (C) 2015 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_PRIVATE_STATIC_ASSERT_H_INCLUDED
#define SOCI_PRIVATE_STATIC_ASSERT_H_INCLUDED
#include "soci-cpp.h"
// This is a simple approximation for C++11 static_assert: generate a
// compile-time error if the given expression evaluates to 0 and make the
// identifier (not string!) msg appear in the error message.
#define SOCI_STATIC_ASSERT(expr) \
struct SOCI_MAKE_UNIQUE_NAME(SociAssert) { unsigned msg: expr; }
#endif // SOCI_PRIVATE_STATIC_ASSERT_H_INCLUDED

View File

@@ -0,0 +1,37 @@
//
// Copyright (C) 2008 Maciej Sobczak with contributions from Artyom Tonkikh
// 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_BACKEND_LOADER_H_INCLUDED
#define SOCI_BACKEND_LOADER_H_INCLUDED
#include "soci/soci-backend.h"
// std
#include <string>
#include <vector>
namespace soci
{
namespace dynamic_backends
{
// used internally by session
backend_factory const & get(std::string const & name);
// provided for advanced user-level management
SOCI_DECL std::vector<std::string> & search_paths();
SOCI_DECL void register_backend(std::string const & name, std::string const & shared_object = std::string());
SOCI_DECL void register_backend(std::string const & name, backend_factory const & factory);
SOCI_DECL std::vector<std::string> list_all();
SOCI_DECL void unload(std::string const & name);
SOCI_DECL void unload_all();
} // namespace dynamic_backends
} // namespace soci
#endif // SOCI_BACKEND_LOADER_H_INCLUDED

View File

@@ -0,0 +1,196 @@
#ifndef SOCI_BIND_VALUES_H_INCLUDED
#define SOCI_BIND_VALUES_H_INCLUDED
#include "exchange-traits.h"
#include "into-type.h"
#include "into.h"
#include "soci-backend.h"
#include "use-type.h"
#include "use.h"
#ifdef HAVE_BOOST
# include <boost/fusion/algorithm/iteration/for_each.hpp>
# include <boost/mpl/bool.hpp>
#endif // HAVE_BOOST
#include <vector>
namespace soci
{
namespace details
{
class use_type_vector: public std::vector<use_type_base *>
{
public:
~use_type_vector()
{
for(iterator iter = begin(), _end = end();
iter != _end; iter++)
delete *iter;
}
void exchange(use_type_ptr const& u) { push_back(u.get()); u.release(); }
template <typename T, typename Indicator>
void exchange(use_container<T, Indicator> const &uc)
{
#ifdef HAVE_BOOST
exchange_(uc, (typename boost::fusion::traits::is_sequence<T>::type *)NULL);
#else
exchange_(uc, NULL);
#endif // HAVE_BOOST
}
private:
#ifdef HAVE_BOOST
template <typename T, typename Indicator>
struct use_sequence
{
use_sequence(use_type_vector &_p, Indicator &_ind)
:p(_p), ind(_ind) {}
template <typename T2>
void operator()(T2 &t2) const
{
p.exchange(use(t2, ind));
}
use_type_vector &p;
Indicator &ind;
private:
SOCI_NOT_COPYABLE(use_sequence)
};
template <typename T>
struct use_sequence<T, details::no_indicator>
{
use_sequence(use_type_vector &_p)
:p(_p) {}
template <typename T2>
void operator()(T2 &t2) const
{
p.exchange(use(t2));
}
use_type_vector &p;
private:
SOCI_NOT_COPYABLE(use_sequence)
};
template <typename T, typename Indicator>
void exchange_(use_container<T, Indicator> const &uc, boost::mpl::true_ * /* fusion sequence */)
{
boost::fusion::for_each(uc.t, use_sequence<T, Indicator>(*this, uc.ind));
}
template <typename T>
void exchange_(use_container<T, details::no_indicator> const &uc, boost::mpl::true_ * /* fusion sequence */)
{
boost::fusion::for_each(uc.t, use_sequence<T, details::no_indicator>(*this));
}
#endif // HAVE_BOOST
template <typename T, typename Indicator>
void exchange_(use_container<T, Indicator> const &uc, ...)
{ exchange(do_use(uc.t, uc.ind, uc.name, typename details::exchange_traits<T>::type_family())); }
template <typename T>
void exchange_(use_container<T, details::no_indicator> const &uc, ...)
{ exchange(do_use(uc.t, uc.name, typename details::exchange_traits<T>::type_family())); }
template <typename T, typename Indicator>
void exchange_(use_container<const T, Indicator> const &uc, ...)
{ exchange(do_use(uc.t, uc.ind, uc.name, typename details::exchange_traits<T>::type_family())); }
template <typename T>
void exchange_(use_container<const T, details::no_indicator> const &uc, ...)
{ exchange(do_use(uc.t, uc.name, typename details::exchange_traits<T>::type_family())); }
};
class into_type_vector: public std::vector<details::into_type_base *>
{
public:
~into_type_vector()
{
for(iterator iter = begin(), _end = end();
iter != _end; iter++)
delete *iter;
}
void exchange(into_type_ptr const& i) { push_back(i.get()); i.release(); }
template <typename T, typename Indicator>
void exchange(into_container<T, Indicator> const &ic)
{
#ifdef HAVE_BOOST
exchange_(ic, (typename boost::fusion::traits::is_sequence<T>::type *)NULL);
#else
exchange_(ic, NULL);
#endif // HAVE_BOOST
}
private:
#ifdef HAVE_BOOST
template <typename T, typename Indicator>
struct into_sequence
{
into_sequence(into_type_vector &_p, Indicator &_ind)
:p(_p), ind(_ind) {}
template <typename T2>
void operator()(T2 &t2) const
{
p.exchange(into(t2, ind));
}
into_type_vector &p;
Indicator &ind;
private:
SOCI_NOT_COPYABLE(into_sequence)
};
template <typename T>
struct into_sequence<T, details::no_indicator>
{
into_sequence(into_type_vector &_p)
:p(_p) {}
template <typename T2>
void operator()(T2 &t2) const
{
p.exchange(into(t2));
}
into_type_vector &p;
private:
SOCI_NOT_COPYABLE(into_sequence)
};
template <typename T, typename Indicator>
void exchange_(into_container<T, Indicator> const &ic, boost::mpl::true_ * /* fusion sequence */)
{
boost::fusion::for_each(ic.t, into_sequence<T, Indicator>(*this, ic.ind));
}
template <typename T>
void exchange_(into_container<T, details::no_indicator> const &ic, boost::mpl::true_ * /* fusion sequence */)
{
boost::fusion::for_each(ic.t, into_sequence<T, details::no_indicator>(*this));
}
#endif // HAVE_BOOST
template <typename T, typename Indicator>
void exchange_(into_container<T, Indicator> const &ic, ...)
{ exchange(do_into(ic.t, ic.ind, typename details::exchange_traits<T>::type_family())); }
template <typename T>
void exchange_(into_container<T, details::no_indicator> const &ic, ...)
{ exchange(do_into(ic.t, typename details::exchange_traits<T>::type_family())); }
};
} // namespace details
}// namespace soci
#endif // SOCI_BIND_VALUES_H_INCLUDED

View File

@@ -0,0 +1,59 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_BLOB_EXCHANGE_H_INCLUDED
#define SOCI_BLOB_EXCHANGE_H_INCLUDED
#include "soci/blob.h"
#include "soci/into-type.h"
#include "soci/use-type.h"
// std
#include <string>
namespace soci
{
namespace details
{
template <>
class into_type<blob> : public standard_into_type
{
public:
into_type(blob & b) : standard_into_type(&b, x_blob) {}
into_type(blob & b, indicator & ind)
: standard_into_type(&b, x_blob, ind) {}
};
template <>
class use_type<blob> : public standard_use_type
{
public:
use_type(blob & b, std::string const & name = std::string())
: standard_use_type(&b, x_blob, false, name) {}
use_type(blob const & b, std::string const & name = std::string())
: standard_use_type(const_cast<blob *>(&b), x_blob, true, name) {}
use_type(blob & b, indicator & ind,
std::string const & name = std::string())
: standard_use_type(&b, x_blob, ind, false, name) {}
use_type(blob const & b, indicator & ind,
std::string const & name = std::string())
: standard_use_type(const_cast<blob *>(&b), x_blob, ind, true, name) {}
};
template <>
struct exchange_traits<soci::blob>
{
typedef basic_type_tag type_family;
enum { x_type = x_blob };
};
} // namespace details
} // namespace soci
#endif // SOCI_BLOB_EXCHANGE_H_INCLUDED

View File

@@ -0,0 +1,47 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_BLOB_H_INCLUDED
#define SOCI_BLOB_H_INCLUDED
#include "soci/soci-platform.h"
// std
#include <cstddef>
namespace soci
{
// basic blob operations
class session;
namespace details
{
class blob_backend;
} // namespace details
class SOCI_DECL blob
{
public:
explicit blob(session & s);
~blob();
std::size_t get_len();
std::size_t read(std::size_t offset, char * buf, std::size_t toRead);
std::size_t write(std::size_t offset, char const * buf,
std::size_t toWrite);
std::size_t append(char const * buf, std::size_t toWrite);
void trim(std::size_t newLen);
details::blob_backend * get_backend() { return backEnd_; }
private:
details::blob_backend * backEnd_;
};
} // namespace soci
#endif

View File

@@ -0,0 +1,28 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_BOOST_FUSION_H_INCLUDED
#define SOCI_BOOST_FUSION_H_INCLUDED
#ifndef SOCI_MAX_FUSION_SEQUENCE_LENGTH
#define SOCI_MAX_FUSION_SEQUENCE_LENGTH 10
#endif
#include "values.h"
#include "type-conversion-traits.h"
// boost
#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/sequence/intrinsic/at.hpp>
#include <boost/fusion/sequence/intrinsic/size.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/support/is_sequence.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/utility/enable_if.hpp>
#endif // SOCI_BOOST_FUSION_H_INCLUDED

View File

@@ -0,0 +1,47 @@
//
// Copyright (C) 2008 Maciej Sobczak
// 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_BOOST_GREGORIAN_DATE_H_INCLUDED
#define SOCI_BOOST_GREGORIAN_DATE_H_INCLUDED
#include "soci/type-conversion-traits.h"
// boost
#include <boost/date_time/gregorian/gregorian_types.hpp>
#include <boost/date_time/gregorian/conversion.hpp>
// std
#include <ctime>
namespace soci
{
template<>
struct type_conversion<boost::gregorian::date>
{
typedef std::tm base_type;
static void from_base(
base_type const & in, indicator ind, boost::gregorian::date & out)
{
if (ind == i_null)
{
throw soci_error("Null value not allowed for this type");
}
out = boost::gregorian::date_from_tm(in);
}
static void to_base(
boost::gregorian::date const & in, base_type & out, indicator & ind)
{
out = boost::gregorian::to_tm(in);
ind = i_ok;
}
};
} // namespace soci
#endif // SOCI_BOOST_GREGORIAN_DATE_H_INCLUDED

View File

@@ -0,0 +1,65 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_BOOST_OPTIONAL_H_INCLUDED
#define SOCI_BOOST_OPTIONAL_H_INCLUDED
#include "soci/type-conversion-traits.h"
// boost
#include <boost/optional.hpp>
namespace soci
{
// tmp is uninitialized
#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ > 6)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
// simple fall-back for boost::optional
template <typename T>
struct type_conversion<boost::optional<T> >
{
typedef typename type_conversion<T>::base_type base_type;
static void from_base(base_type const & in, indicator ind,
boost::optional<T> & out)
{
if (ind == i_null)
{
out.reset();
}
else
{
T tmp;
type_conversion<T>::from_base(in, ind, tmp);
out = tmp;
}
}
static void to_base(boost::optional<T> const & in,
base_type & out, indicator & ind)
{
if (in.is_initialized())
{
type_conversion<T>::to_base(in.get(), out, ind);
}
else
{
ind = i_null;
}
}
};
} // namespace soci
#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ > 6)
#pragma GCC diagnostic pop
#endif
#endif // SOCI_BOOST_OPTIONAL_H_INCLUDED

View File

@@ -0,0 +1,18 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_BOOST_TUPLE_H_INCLUDED
#define SOCI_BOOST_TUPLE_H_INCLUDED
#include "values.h"
#include "type-conversion-traits.h"
// boost
#include <boost/tuple/tuple.hpp>
#include <boost/fusion/adapted/boost_tuple.hpp>
#endif // SOCI_BOOST_TUPLE_H_INCLUDED

View File

@@ -0,0 +1,68 @@
//
// Copyright (C) 2013 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_CONNECTION_PARAMETERS_H_INCLUDED
#define SOCI_CONNECTION_PARAMETERS_H_INCLUDED
#include "soci/soci-platform.h"
#include <map>
#include <string>
namespace soci
{
class backend_factory;
// Simple container for the information used when opening a session.
class SOCI_DECL connection_parameters
{
public:
connection_parameters();
connection_parameters(backend_factory const & factory, std::string const & connectString);
connection_parameters(std::string const & backendName, std::string const & connectString);
explicit connection_parameters(std::string const & fullConnectString);
// Default copy ctor, assignment operator and dtor are all OK for us.
// Retrieve the backend and the connection strings specified in the ctor.
backend_factory const * get_factory() const { return factory_; }
std::string const & get_connect_string() const { return connectString_; }
// Set the value of the given option, overwriting any previous value.
void set_option(const char * name, std::string const & value)
{
options_[name] = value;
}
// Return true if the option with the given name was found and fill the
// provided parameter with its value.
bool get_option(const char * name, std::string & value) const
{
Options::const_iterator const it = options_.find(name);
if (it == options_.end())
return false;
value = it->second;
return true;
}
private:
// The backend and connection string specified in our ctor.
backend_factory const * factory_;
std::string connectString_;
// We store all the values as strings for simplicity.
typedef std::map<std::string, std::string> Options;
Options options_;
};
} // namespace soci
#endif // SOCI_CONNECTION_PARAMETERS_H_INCLUDED

View File

@@ -0,0 +1,39 @@
//
// Copyright (C) 2008 Maciej Sobczak
// 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_CONNECTION_POOL_H_INCLUDED
#define SOCI_CONNECTION_POOL_H_INCLUDED
#include "soci/soci-platform.h"
// std
#include <cstddef>
namespace soci
{
class session;
class SOCI_DECL connection_pool
{
public:
explicit connection_pool(std::size_t size);
~connection_pool();
session & at(std::size_t pos);
std::size_t lease();
bool try_lease(std::size_t & pos, int timeout);
void give_back(std::size_t pos);
private:
struct connection_pool_impl;
connection_pool_impl * pimpl_;
};
}
#endif // SOCI_CONNECTION_POOL_H_INCLUDED

View File

@@ -0,0 +1,294 @@
//
// Copyright (C) 2011-2013 Denis Chapligin
// Copyright (C) 2004-2006 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)
//
#ifndef SOCI_DB2_H_INCLUDED
#define SOCI_DB2_H_INCLUDED
#ifdef _WIN32
# ifdef SOCI_DLL
# ifdef SOCI_DB2_SOURCE
# define SOCI_DB2_DECL __declspec(dllexport)
# else
# define SOCI_DB2_DECL __declspec(dllimport)
# endif // SOCI_DB2_SOURCE
# endif // SOCI_DLL
#endif // _WIN32
//
// If SOCI_DB2_DECL isn't defined yet define it now
#ifndef SOCI_DB2_DECL
# define SOCI_DB2_DECL
#endif
#include <soci/soci-backend.h>
#include <cstddef>
#include <string>
#include <vector>
#include <iostream>
#include <sstream>
#include <string>
#include <cstring>
#include <sqlcli1.h>
namespace soci
{
namespace details { namespace db2
{
enum binding_method
{
BOUND_BY_NONE,
BOUND_BY_NAME,
BOUND_BY_POSITION
};
inline SQLPOINTER int_as_ptr(int n)
{
union
{
SQLPOINTER p;
int n;
} u;
u.n = n;
return u.p;
}
}}
static const std::size_t maxBuffer = 1024 * 1024 * 1024; //CLI limit is about 3 GB, but 1GB should be enough
class db2_soci_error : public soci_error {
public:
db2_soci_error(std::string const & msg, SQLRETURN rc) : soci_error(msg),errorCode(rc) {};
~db2_soci_error() throw() { };
//We have to extract error information before exception throwing, cause CLI handles could be broken at the construction time
static const std::string sqlState(std::string const & msg,const SQLSMALLINT htype,const SQLHANDLE hndl);
SQLRETURN errorCode;
};
struct db2_statement_backend;
struct SOCI_DB2_DECL db2_standard_into_type_backend : details::standard_into_type_backend
{
db2_standard_into_type_backend(db2_statement_backend &st)
: statement_(st),buf(NULL)
{}
void define_by_pos(int& position, void* data, details::exchange_type type);
void pre_fetch();
void post_fetch(bool gotData, bool calledFromFetch, indicator* ind);
void clean_up();
db2_statement_backend& statement_;
char* buf;
void *data;
details::exchange_type type;
int position;
SQLSMALLINT cType;
SQLLEN valueLen;
};
struct SOCI_DB2_DECL db2_vector_into_type_backend : details::vector_into_type_backend
{
db2_vector_into_type_backend(db2_statement_backend &st)
: statement_(st),buf(NULL)
{}
void define_by_pos(int& position, void* data, details::exchange_type type);
void pre_fetch();
void post_fetch(bool gotData, indicator* ind);
void resize(std::size_t sz);
std::size_t size();
void clean_up();
db2_statement_backend& statement_;
void prepare_indicators(std::size_t size);
SQLLEN *indptr;
std::vector<SQLLEN> indVec;
void *data;
char *buf;
int position_;
details::exchange_type type;
SQLSMALLINT cType;
std::size_t colSize;
};
struct SOCI_DB2_DECL db2_standard_use_type_backend : details::standard_use_type_backend
{
db2_standard_use_type_backend(db2_statement_backend &st)
: statement_(st),buf(NULL),ind(0)
{}
void bind_by_pos(int& position, void* data, details::exchange_type type, bool readOnly);
void bind_by_name(std::string const& name, void* data, details::exchange_type type, bool readOnly);
void pre_use(indicator const* ind);
void post_use(bool gotData, indicator* ind);
void clean_up();
db2_statement_backend& statement_;
void *prepare_for_bind(void *data, SQLLEN &size, SQLSMALLINT &sqlType, SQLSMALLINT &cType);
void *data;
details::exchange_type type;
int position;
std::string name;
char* buf;
SQLLEN ind;
};
struct SOCI_DB2_DECL db2_vector_use_type_backend : details::vector_use_type_backend
{
db2_vector_use_type_backend(db2_statement_backend &st)
: statement_(st),buf(NULL) {}
void bind_by_pos(int& position, void* data, details::exchange_type type);
void bind_by_name(std::string const& name, void* data, details::exchange_type type);
void pre_use(indicator const* ind);
std::size_t size();
void clean_up();
db2_statement_backend& statement_;
void prepare_indicators(std::size_t size);
void prepare_for_bind(void *&data, SQLUINTEGER &size,SQLSMALLINT &sqlType, SQLSMALLINT &cType);
void bind_helper(int &position, void *data, details::exchange_type type);
SQLLEN *indptr;
std::vector<SQLLEN> indVec;
void *data;
char *buf;
details::exchange_type type;
std::size_t colSize;
};
struct db2_session_backend;
struct SOCI_DB2_DECL db2_statement_backend : details::statement_backend
{
db2_statement_backend(db2_session_backend &session);
void alloc();
void clean_up();
void prepare(std::string const& query, details::statement_type eType);
exec_fetch_result execute(int number);
exec_fetch_result fetch(int number);
long long get_affected_rows();
int get_number_of_rows();
std::string get_parameter_name(int index) const;
std::string rewrite_for_procedure_call(std::string const& query);
int prepare_for_describe();
void describe_column(int colNum, data_type& dtype, std::string& columnName);
size_t column_size(int col);
db2_standard_into_type_backend* make_into_type_backend();
db2_standard_use_type_backend* make_use_type_backend();
db2_vector_into_type_backend* make_vector_into_type_backend();
db2_vector_use_type_backend* make_vector_use_type_backend();
db2_session_backend& session_;
SQLHANDLE hStmt;
std::string query_;
std::vector<std::string> names_;
bool hasVectorUseElements;
SQLUINTEGER numRowsFetched;
details::db2::binding_method use_binding_method_;
};
struct db2_rowid_backend : details::rowid_backend
{
db2_rowid_backend(db2_session_backend &session);
~db2_rowid_backend();
};
struct db2_blob_backend : details::blob_backend
{
db2_blob_backend(db2_session_backend& session);
~db2_blob_backend();
std::size_t get_len();
std::size_t read(std::size_t offset, char* buf, std::size_t toRead);
std::size_t write(std::size_t offset, char const* buf, std::size_t toWrite);
std::size_t append(char const* buf, std::size_t toWrite);
void trim(std::size_t newLen);
db2_session_backend& session_;
};
struct db2_session_backend : details::session_backend
{
db2_session_backend(connection_parameters const& parameters);
~db2_session_backend();
void begin();
void commit();
void rollback();
std::string get_backend_name() const { return "DB2"; }
void clean_up();
db2_statement_backend* make_statement_backend();
db2_rowid_backend* make_rowid_backend();
db2_blob_backend* make_blob_backend();
void parseConnectString(std::string const &);
void parseKeyVal(std::string const &);
std::string dsn;
std::string username;
std::string password;
bool autocommit;
bool in_transaction;
SQLHANDLE hEnv; /* Environment handle */
SQLHANDLE hDbc; /* Connection handle */
};
struct SOCI_DB2_DECL db2_backend_factory : backend_factory
{
db2_backend_factory() {}
db2_session_backend* make_session(
connection_parameters const & parameters) const;
};
extern SOCI_DB2_DECL db2_backend_factory const db2;
extern "C"
{
// for dynamic backend loading
SOCI_DB2_DECL backend_factory const* factory_db2();
SOCI_DB2_DECL void register_factory_db2();
} // extern "C"
} // namespace soci
#endif // SOCI_DB2_H_INCLUDED

View File

@@ -0,0 +1,194 @@
//
// Copyright (C) 2004-2006 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)
//
#ifndef SOCI_EMPTY_H_INCLUDED
#define SOCI_EMPTY_H_INCLUDED
#ifdef _WIN32
# ifdef SOCI_DLL
# ifdef SOCI_EMPTY_SOURCE
# define SOCI_EMPTY_DECL __declspec(dllexport)
# else
# define SOCI_EMPTY_DECL __declspec(dllimport)
# endif // SOCI_EMPTY_SOURCE
# endif // SOCI_DLL
#endif // _WIN32
//
// If SOCI_EMPTY_DECL isn't defined yet define it now
#ifndef SOCI_EMPTY_DECL
# define SOCI_EMPTY_DECL
#endif
#include <soci/soci-backend.h>
#include <cstddef>
#include <string>
namespace soci
{
struct empty_statement_backend;
struct SOCI_EMPTY_DECL empty_standard_into_type_backend : details::standard_into_type_backend
{
empty_standard_into_type_backend(empty_statement_backend &st)
: statement_(st)
{}
void define_by_pos(int& position, void* data, details::exchange_type type);
void pre_fetch();
void post_fetch(bool gotData, bool calledFromFetch, indicator* ind);
void clean_up();
empty_statement_backend& statement_;
};
struct SOCI_EMPTY_DECL empty_vector_into_type_backend : details::vector_into_type_backend
{
empty_vector_into_type_backend(empty_statement_backend &st)
: statement_(st)
{}
void define_by_pos(int& position, void* data, details::exchange_type type);
void pre_fetch();
void post_fetch(bool gotData, indicator* ind);
void resize(std::size_t sz);
std::size_t size();
void clean_up();
empty_statement_backend& statement_;
};
struct SOCI_EMPTY_DECL empty_standard_use_type_backend : details::standard_use_type_backend
{
empty_standard_use_type_backend(empty_statement_backend &st)
: statement_(st)
{}
void bind_by_pos(int& position, void* data, details::exchange_type type, bool readOnly);
void bind_by_name(std::string const& name, void* data, details::exchange_type type, bool readOnly);
void pre_use(indicator const* ind);
void post_use(bool gotData, indicator* ind);
void clean_up();
empty_statement_backend& statement_;
};
struct SOCI_EMPTY_DECL empty_vector_use_type_backend : details::vector_use_type_backend
{
empty_vector_use_type_backend(empty_statement_backend &st)
: statement_(st) {}
void bind_by_pos(int& position, void* data, details::exchange_type type);
void bind_by_name(std::string const& name, void* data, details::exchange_type type);
void pre_use(indicator const* ind);
std::size_t size();
void clean_up();
empty_statement_backend& statement_;
};
struct empty_session_backend;
struct SOCI_EMPTY_DECL empty_statement_backend : details::statement_backend
{
empty_statement_backend(empty_session_backend &session);
void alloc();
void clean_up();
void prepare(std::string const& query, details::statement_type eType);
exec_fetch_result execute(int number);
exec_fetch_result fetch(int number);
long long get_affected_rows();
int get_number_of_rows();
std::string get_parameter_name(int index) const;
std::string rewrite_for_procedure_call(std::string const& query);
int prepare_for_describe();
void describe_column(int colNum, data_type& dtype, std::string& columnName);
empty_standard_into_type_backend* make_into_type_backend();
empty_standard_use_type_backend* make_use_type_backend();
empty_vector_into_type_backend* make_vector_into_type_backend();
empty_vector_use_type_backend* make_vector_use_type_backend();
empty_session_backend& session_;
};
struct empty_rowid_backend : details::rowid_backend
{
empty_rowid_backend(empty_session_backend &session);
~empty_rowid_backend();
};
struct empty_blob_backend : details::blob_backend
{
empty_blob_backend(empty_session_backend& session);
~empty_blob_backend();
std::size_t get_len();
std::size_t read(std::size_t offset, char* buf, std::size_t toRead);
std::size_t write(std::size_t offset, char const* buf, std::size_t toWrite);
std::size_t append(char const* buf, std::size_t toWrite);
void trim(std::size_t newLen);
empty_session_backend& session_;
};
struct empty_session_backend : details::session_backend
{
empty_session_backend(connection_parameters const& parameters);
~empty_session_backend();
void begin();
void commit();
void rollback();
std::string get_backend_name() const { return "empty"; }
void clean_up();
empty_statement_backend* make_statement_backend();
empty_rowid_backend* make_rowid_backend();
empty_blob_backend* make_blob_backend();
};
struct SOCI_EMPTY_DECL empty_backend_factory : backend_factory
{
empty_backend_factory() {}
empty_session_backend* make_session(connection_parameters const& parameters) const;
};
extern SOCI_EMPTY_DECL empty_backend_factory const empty;
extern "C"
{
// for dynamic backend loading
SOCI_EMPTY_DECL backend_factory const* factory_empty();
SOCI_EMPTY_DECL void register_factory_empty();
} // extern "C"
} // namespace soci
#endif // SOCI_EMPTY_H_INCLUDED

View File

@@ -0,0 +1,50 @@
//
// Copyright (C) 2004-2008 Maciej Sobczak
// Copyright (C) 2015 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_ERROR_H_INCLUDED
#define SOCI_ERROR_H_INCLUDED
#include "soci/soci-platform.h"
// std
#include <stdexcept>
#include <string>
namespace soci
{
class SOCI_DECL soci_error : public std::runtime_error
{
public:
explicit soci_error(std::string const & msg);
soci_error(soci_error const& e);
soci_error& operator=(soci_error const& e);
virtual ~soci_error() throw();
// Returns just the error message itself, without the context.
std::string get_error_message() const;
// Returns the full error message combining the message given to the ctor
// with all the available context records.
virtual char const* what() const throw();
// This is used only by SOCI itself to provide more information about the
// exception as it bubbles up. It can be called multiple times, with the
// first call adding the lowest level context and the last one -- the
// highest level context.
void add_context(std::string const& context);
private:
// Optional extra information (currently just the context data).
class soci_error_extra_info* info_;
};
} // namespace soci
#endif // SOCI_ERROR_H_INCLUDED

View File

@@ -0,0 +1,138 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_EXCHANGE_TRAITS_H_INCLUDED
#define SOCI_EXCHANGE_TRAITS_H_INCLUDED
#include "soci/type-conversion-traits.h"
#include "soci/soci-backend.h"
// std
#include <ctime>
#include <string>
#include <vector>
namespace soci
{
namespace details
{
struct basic_type_tag {};
struct user_type_tag {};
template <typename T>
struct exchange_traits
{
// this is used for tag-dispatch between implementations for basic types
// and user-defined types
typedef user_type_tag type_family;
enum // anonymous
{
x_type =
exchange_traits
<
typename type_conversion<T>::base_type
>::x_type
};
};
template <>
struct exchange_traits<short>
{
typedef basic_type_tag type_family;
enum { x_type = x_short };
};
template <>
struct exchange_traits<unsigned short> : exchange_traits<short>
{
};
template <>
struct exchange_traits<int>
{
typedef basic_type_tag type_family;
enum { x_type = x_integer };
};
template <>
struct exchange_traits<unsigned int> : exchange_traits<int>
{
};
template <>
struct exchange_traits<char>
{
typedef basic_type_tag type_family;
enum { x_type = x_char };
};
template <>
struct exchange_traits<long long>
{
typedef basic_type_tag type_family;
enum { x_type = x_long_long };
};
template <>
struct exchange_traits<unsigned long long>
{
typedef basic_type_tag type_family;
enum { x_type = x_unsigned_long_long };
};
// long must be mapped either to x_integer or x_long_long:
template<int long_size> struct long_traits_helper;
template<> struct long_traits_helper<4> { enum { x_type = x_integer }; };
template<> struct long_traits_helper<8> { enum { x_type = x_long_long }; };
template <>
struct exchange_traits<long int>
{
typedef basic_type_tag type_family;
enum { x_type = long_traits_helper<sizeof(long int)>::x_type };
};
template <>
struct exchange_traits<unsigned long> : exchange_traits<long>
{
};
template <>
struct exchange_traits<double>
{
typedef basic_type_tag type_family;
enum { x_type = x_double };
};
template <>
struct exchange_traits<std::string>
{
typedef basic_type_tag type_family;
enum { x_type = x_stdstring };
};
template <>
struct exchange_traits<std::tm>
{
typedef basic_type_tag type_family;
enum { x_type = x_stdtm };
};
template <typename T>
struct exchange_traits<std::vector<T> >
{
typedef typename exchange_traits<T>::type_family type_family;
enum { x_type = exchange_traits<T>::x_type };
};
} // namespace details
} // namespace soci
#endif // SOCI_EXCHANGE_TRAITS_H_INCLUDED

View File

@@ -0,0 +1,348 @@
//
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, Rafal Bobrowski
// 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_FIREBIRD_H_INCLUDED
#define SOCI_FIREBIRD_H_INCLUDED
#ifdef _WIN32
# ifdef SOCI_DLL
# ifdef SOCI_FIREBIRD_SOURCE
# define SOCI_FIREBIRD_DECL __declspec(dllexport)
# else
# define SOCI_FIREBIRD_DECL __declspec(dllimport)
# endif // SOCI_DLL
# endif // SOCI_FIREBIRD_SOURCE
#endif // _WIN32
//
// If SOCI_FIREBIRD_DECL isn't defined yet define it now
#ifndef SOCI_FIREBIRD_DECL
# define SOCI_FIREBIRD_DECL
#endif
#ifdef _WIN32
#include <ciso646> // To understand and/or/not on MSVC9
#endif
#include <soci/soci-backend.h>
#include <ibase.h> // FireBird
#include <cstdlib>
#include <vector>
#include <string>
namespace soci
{
std::size_t const stat_size = 20;
// size of buffer for error messages. All examples use this value.
// Anyone knows, where it is stated that 512 bytes is enough ?
std::size_t const SOCI_FIREBIRD_ERRMSG = 512;
class SOCI_FIREBIRD_DECL firebird_soci_error : public soci_error
{
public:
firebird_soci_error(std::string const & msg,
ISC_STATUS const * status = 0);
~firebird_soci_error() throw() {};
std::vector<ISC_STATUS> status_;
};
enum BuffersType
{
eStandard, eVector
};
struct firebird_statement_backend;
struct firebird_standard_into_type_backend : details::standard_into_type_backend
{
firebird_standard_into_type_backend(firebird_statement_backend &st)
: statement_(st), buf_(NULL)
{}
virtual void define_by_pos(int &position,
void *data, details::exchange_type type);
virtual void pre_fetch();
virtual void post_fetch(bool gotData, bool calledFromFetch,
indicator *ind);
virtual void clean_up();
firebird_statement_backend &statement_;
virtual void exchangeData();
void *data_;
details::exchange_type type_;
int position_;
char *buf_;
short indISCHolder_;
};
struct firebird_vector_into_type_backend : details::vector_into_type_backend
{
firebird_vector_into_type_backend(firebird_statement_backend &st)
: statement_(st), buf_(NULL)
{}
virtual void define_by_pos(int &position,
void *data, details::exchange_type type);
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 void clean_up();
firebird_statement_backend &statement_;
virtual void exchangeData(std::size_t row);
void *data_;
details::exchange_type type_;
int position_;
char *buf_;
short indISCHolder_;
};
struct firebird_standard_use_type_backend : details::standard_use_type_backend
{
firebird_standard_use_type_backend(firebird_statement_backend &st)
: statement_(st), buf_(NULL), indISCHolder_(0)
{}
virtual void bind_by_pos(int &position,
void *data, details::exchange_type type, bool readOnly);
virtual void bind_by_name(std::string const &name,
void *data, details::exchange_type type, bool readOnly);
virtual void pre_use(indicator const *ind);
virtual void post_use(bool gotData, indicator *ind);
virtual void clean_up();
firebird_statement_backend &statement_;
virtual void exchangeData();
void *data_;
details::exchange_type type_;
int position_;
char *buf_;
short indISCHolder_;
};
struct firebird_vector_use_type_backend : details::vector_use_type_backend
{
firebird_vector_use_type_backend(firebird_statement_backend &st)
: statement_(st), inds_(NULL), buf_(NULL), indISCHolder_(0)
{}
virtual void bind_by_pos(int &position,
void *data, details::exchange_type type);
virtual void bind_by_name(std::string const &name,
void *data, details::exchange_type type);
virtual void pre_use(indicator const *ind);
virtual std::size_t size();
virtual void clean_up();
firebird_statement_backend &statement_;
virtual void exchangeData(std::size_t row);
void *data_;
details::exchange_type type_;
int position_;
indicator const *inds_;
char *buf_;
short indISCHolder_;
};
struct firebird_session_backend;
struct firebird_statement_backend : details::statement_backend
{
firebird_statement_backend(firebird_session_backend &session);
virtual void alloc();
virtual void clean_up();
virtual void prepare(std::string const &query,
details::statement_type eType);
virtual exec_fetch_result execute(int number);
virtual exec_fetch_result fetch(int number);
virtual long long get_affected_rows();
virtual int get_number_of_rows();
virtual std::string get_parameter_name(int index) const;
virtual std::string rewrite_for_procedure_call(std::string const &query);
virtual int prepare_for_describe();
virtual void describe_column(int colNum, data_type &dtype,
std::string &columnName);
virtual firebird_standard_into_type_backend * make_into_type_backend();
virtual firebird_standard_use_type_backend * make_use_type_backend();
virtual firebird_vector_into_type_backend * make_vector_into_type_backend();
virtual firebird_vector_use_type_backend * make_vector_use_type_backend();
firebird_session_backend &session_;
isc_stmt_handle stmtp_;
XSQLDA * sqldap_;
XSQLDA * sqlda2p_;
bool boundByName_;
bool boundByPos_;
friend struct firebird_vector_into_type_backend;
friend struct firebird_standard_into_type_backend;
friend struct firebird_vector_use_type_backend;
friend struct firebird_standard_use_type_backend;
protected:
int rowsFetched_;
bool endOfRowSet_;
long long rowsAffectedBulk_; // number of rows affected by the last bulk operation
virtual void exchangeData(bool gotData, int row);
virtual void prepareSQLDA(XSQLDA ** sqldap, short size = 10);
virtual void rewriteQuery(std::string const & query,
std::vector<char> & buffer);
virtual void rewriteParameters(std::string const & src,
std::vector<char> & dst);
BuffersType intoType_;
BuffersType useType_;
std::vector<std::vector<indicator> > inds_;
std::vector<void*> intos_;
std::vector<void*> uses_;
// named parameters
std::map <std::string, int> names_;
bool procedure_;
};
struct firebird_blob_backend : details::blob_backend
{
firebird_blob_backend(firebird_session_backend &session);
~firebird_blob_backend();
virtual std::size_t get_len();
virtual std::size_t read(std::size_t offset, char *buf,
std::size_t toRead);
virtual std::size_t write(std::size_t offset, char const *buf,
std::size_t toWrite);
virtual std::size_t append(char const *buf, std::size_t toWrite);
virtual void trim(std::size_t newLen);
firebird_session_backend &session_;
virtual void save();
virtual void assign(ISC_QUAD const & bid)
{
cleanUp();
bid_ = bid;
from_db_ = true;
}
// BLOB id from in database
ISC_QUAD bid_;
// BLOB id was fetched from database (true)
// or this is new BLOB
bool from_db_;
// BLOB handle
isc_blob_handle bhp_;
protected:
virtual void open();
virtual long getBLOBInfo();
virtual void load();
virtual void writeBuffer(std::size_t offset, char const * buf,
std::size_t toWrite);
virtual void cleanUp();
// buffer for BLOB data
std::vector<char> data_;
bool loaded_;
long max_seg_size_;
};
struct firebird_session_backend : details::session_backend
{
firebird_session_backend(connection_parameters const & parameters);
~firebird_session_backend();
virtual void begin();
virtual void commit();
virtual void rollback();
virtual bool get_next_sequence_value(session & s,
std::string const & sequence, long & value);
virtual std::string get_backend_name() const { return "firebird"; }
void cleanUp();
virtual firebird_statement_backend * make_statement_backend();
virtual details::rowid_backend* make_rowid_backend();
virtual firebird_blob_backend * make_blob_backend();
bool get_option_decimals_as_strings() { return decimals_as_strings_; }
// Returns the pointer to the current transaction handle, starting a new
// transaction if necessary.
//
// The returned pointer should
isc_tr_handle* current_transaction();
isc_db_handle dbhp_;
private:
isc_tr_handle trhp_;
bool decimals_as_strings_;
};
struct firebird_backend_factory : backend_factory
{
firebird_backend_factory() {}
virtual firebird_session_backend * make_session(
connection_parameters const & parameters) const;
};
extern SOCI_FIREBIRD_DECL firebird_backend_factory const firebird;
extern "C"
{
// for dynamic backend loading
SOCI_FIREBIRD_DECL backend_factory const * factory_firebird();
SOCI_FIREBIRD_DECL void register_factory_firebird();
} // extern "C"
} // namespace soci
#endif // SOCI_FIREBIRD_H_INCLUDED

View File

@@ -0,0 +1,164 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_INTO_TYPE_H_INCLUDED
#define SOCI_INTO_TYPE_H_INCLUDED
#include "soci/soci-backend.h"
#include "soci/type-ptr.h"
#include "soci/exchange-traits.h"
// std
#include <cstddef>
#include <vector>
namespace soci
{
class session;
namespace details
{
class prepare_temp_type;
class standard_into_type_backend;
class vector_into_type_backend;
class statement_impl;
// this is intended to be a base class for all classes that deal with
// defining output data
class into_type_base
{
public:
virtual ~into_type_base() {}
virtual void define(statement_impl & st, int & position) = 0;
virtual void pre_fetch() = 0;
virtual void post_fetch(bool gotData, bool calledFromFetch) = 0;
virtual void clean_up() = 0;
virtual std::size_t size() const = 0; // returns the number of elements
virtual void resize(std::size_t /* sz */) {} // used for vectors only
};
typedef type_ptr<into_type_base> into_type_ptr;
// standard types
class SOCI_DECL standard_into_type : public into_type_base
{
public:
standard_into_type(void * data, exchange_type type)
: data_(data), type_(type), ind_(NULL), backEnd_(NULL) {}
standard_into_type(void * data, exchange_type type, indicator & ind)
: data_(data), type_(type), ind_(&ind), backEnd_(NULL) {}
virtual ~standard_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();
virtual std::size_t size() const { return 1; }
// conversion hook (from base type to arbitrary user type)
virtual void convert_from_base() {}
void * data_;
exchange_type type_;
indicator * ind_;
standard_into_type_backend * backEnd_;
};
// into type base class for vectors
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) {}
vector_into_type(void * data, exchange_type type,
std::vector<indicator> & ind)
: data_(data), type_(type), indVec_(&ind), 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();
virtual void resize(std::size_t sz);
virtual std::size_t size() const;
void * data_;
exchange_type type_;
std::vector<indicator> * indVec_;
vector_into_type_backend * backEnd_;
virtual void convert_from_base() {}
};
// implementation for the basic types (those which are supported by the library
// out of the box without user-provided conversions)
template <typename T>
class into_type : public standard_into_type
{
public:
into_type(T & t)
: standard_into_type(&t,
static_cast<exchange_type>(exchange_traits<T>::x_type)) {}
into_type(T & t, indicator & ind)
: standard_into_type(&t,
static_cast<exchange_type>(exchange_traits<T>::x_type), ind) {}
};
template <typename T>
class into_type<std::vector<T> > : public vector_into_type
{
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::vector<indicator> & ind)
: vector_into_type(&v,
static_cast<exchange_type>(exchange_traits<T>::x_type), ind) {}
};
// helper dispatchers for basic types
template <typename T>
into_type_ptr do_into(T & t, basic_type_tag)
{
return into_type_ptr(new into_type<T>(t));
}
template <typename T>
into_type_ptr do_into(T & t, indicator & ind, basic_type_tag)
{
return into_type_ptr(new into_type<T>(t, ind));
}
template <typename T>
into_type_ptr do_into(T & t, std::vector<indicator> & ind, basic_type_tag)
{
return into_type_ptr(new into_type<T>(t, ind));
}
} // namespace details
} // namespace soci
#endif // SOCI_INTO_TYPE_H_INCLUDED

View File

@@ -0,0 +1,72 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_INTO_H_INCLUDED
#define SOCI_INTO_H_INCLUDED
#include "soci/into-type.h"
#include "soci/exchange-traits.h"
#include "soci/type-conversion.h"
// std
#include <cstddef>
#include <vector>
namespace soci
{
// the into function is a helper for defining output variables
// these helpers work with both basic and user-defined types thanks to
// the tag-dispatching, as defined in exchange_traits template
namespace details
{
template <typename T, typename Indicator>
struct into_container
{
into_container(T &_t, Indicator &_ind)
: t(_t), ind(_ind) {}
T &t;
Indicator &ind;
private:
SOCI_NOT_ASSIGNABLE(into_container)
};
typedef void no_indicator;
template <typename T>
struct into_container<T, no_indicator>
{
into_container(T &_t)
: t(_t) {}
T &t;
private:
SOCI_NOT_ASSIGNABLE(into_container)
};
} // namespace details
template <typename T>
details::into_container<T, details::no_indicator>
into(T &t)
{ return details::into_container<T, details::no_indicator>(t); }
template <typename T, typename Indicator>
details::into_container<T, Indicator>
into(T &t, Indicator &ind)
{ return details::into_container<T, Indicator>(t, ind); }
// for char buffer with run-time size information
template <typename T>
details::into_type_ptr into(T & t, std::size_t bufSize)
{
return details::into_type_ptr(new details::into_type<T>(t, bufSize));
}
} // namespace soci
#endif // SOCI_INTO_H_INCLUDED

View File

@@ -0,0 +1,276 @@
//
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton
// MySQL backend copyright (C) 2006 Pawel Aleksander Fedorynski
// 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_MYSQL_H_INCLUDED
#define SOCI_MYSQL_H_INCLUDED
#ifdef _WIN32
# ifdef SOCI_DLL
# ifdef SOCI_MYSQL_SOURCE
# define SOCI_MYSQL_DECL __declspec(dllexport)
# else
# define SOCI_MYSQL_DECL __declspec(dllimport)
# endif // SOCI_DLL
# endif // SOCI_MYSQL_SOURCE
#endif // _WIN32
//
// If SOCI_MYSQL_DECL isn't defined yet define it now
#ifndef SOCI_MYSQL_DECL
# define SOCI_MYSQL_DECL
#endif
#include <soci/soci-backend.h>
#ifdef _WIN32
#include <winsock.h> // SOCKET
#endif // _WIN32
#include <mysql.h> // MySQL Client
#include <vector>
namespace soci
{
class mysql_soci_error : public soci_error
{
public:
mysql_soci_error(std::string const & msg, int errNum)
: soci_error(msg), err_num_(errNum) {}
unsigned int err_num_;
};
struct mysql_statement_backend;
struct mysql_standard_into_type_backend : details::standard_into_type_backend
{
mysql_standard_into_type_backend(mysql_statement_backend &st)
: statement_(st) {}
virtual void define_by_pos(int &position,
void *data, details::exchange_type type);
virtual void pre_fetch();
virtual void post_fetch(bool gotData, bool calledFromFetch,
indicator *ind);
virtual void clean_up();
mysql_statement_backend &statement_;
void *data_;
details::exchange_type type_;
int position_;
};
struct mysql_vector_into_type_backend : details::vector_into_type_backend
{
mysql_vector_into_type_backend(mysql_statement_backend &st)
: statement_(st) {}
virtual void define_by_pos(int &position,
void *data, details::exchange_type type);
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 void clean_up();
mysql_statement_backend &statement_;
void *data_;
details::exchange_type type_;
int position_;
};
struct mysql_standard_use_type_backend : details::standard_use_type_backend
{
mysql_standard_use_type_backend(mysql_statement_backend &st)
: statement_(st), position_(0), buf_(NULL) {}
virtual void bind_by_pos(int &position,
void *data, details::exchange_type type, bool readOnly);
virtual void bind_by_name(std::string const &name,
void *data, details::exchange_type type, bool readOnly);
virtual void pre_use(indicator const *ind);
virtual void post_use(bool gotData, indicator *ind);
virtual void clean_up();
mysql_statement_backend &statement_;
void *data_;
details::exchange_type type_;
int position_;
std::string name_;
char *buf_;
};
struct mysql_vector_use_type_backend : details::vector_use_type_backend
{
mysql_vector_use_type_backend(mysql_statement_backend &st)
: statement_(st), position_(0) {}
virtual void bind_by_pos(int &position,
void *data, details::exchange_type type);
virtual void bind_by_name(std::string const &name,
void *data, details::exchange_type type);
virtual void pre_use(indicator const *ind);
virtual std::size_t size();
virtual void clean_up();
mysql_statement_backend &statement_;
void *data_;
details::exchange_type type_;
int position_;
std::string name_;
std::vector<char *> buffers_;
};
struct mysql_session_backend;
struct mysql_statement_backend : details::statement_backend
{
mysql_statement_backend(mysql_session_backend &session);
virtual void alloc();
virtual void clean_up();
virtual void prepare(std::string const &query,
details::statement_type eType);
virtual exec_fetch_result execute(int number);
virtual exec_fetch_result fetch(int number);
virtual long long get_affected_rows();
virtual int get_number_of_rows();
virtual std::string get_parameter_name(int index) const;
virtual std::string rewrite_for_procedure_call(std::string const &query);
virtual int prepare_for_describe();
virtual void describe_column(int colNum, data_type &dtype,
std::string &columnName);
virtual mysql_standard_into_type_backend * make_into_type_backend();
virtual mysql_standard_use_type_backend * make_use_type_backend();
virtual mysql_vector_into_type_backend * make_vector_into_type_backend();
virtual mysql_vector_use_type_backend * make_vector_use_type_backend();
mysql_session_backend &session_;
MYSQL_RES *result_;
// The query is split into chunks, separated by the named parameters;
// e.g. for "SELECT id FROM ttt WHERE name = :foo AND gender = :bar"
// we will have query chunks "SELECT id FROM ttt WHERE name = ",
// "AND gender = " and names "foo", "bar".
std::vector<std::string> queryChunks_;
std::vector<std::string> names_; // list of names for named binds
long long rowsAffectedBulk_; // number of rows affected by the last bulk operation
int numberOfRows_; // number of rows retrieved from the server
int currentRow_; // "current" row number to consume in postFetch
int rowsToConsume_; // number of rows to be consumed in postFetch
bool justDescribed_; // to optimize row description with immediately
// following actual statement execution
// Prefetch the row offsets in order to use mysql_row_seek() for
// random access to rows, since mysql_data_seek() is expensive.
std::vector<MYSQL_ROW_OFFSET> resultRowOffsets_;
bool hasIntoElements_;
bool hasVectorIntoElements_;
bool hasUseElements_;
bool hasVectorUseElements_;
// the following maps are used for finding data buffers according to
// use elements specified by the user
typedef std::map<int, char **> UseByPosBuffersMap;
UseByPosBuffersMap useByPosBuffers_;
typedef std::map<std::string, char **> UseByNameBuffersMap;
UseByNameBuffersMap useByNameBuffers_;
};
struct mysql_rowid_backend : details::rowid_backend
{
mysql_rowid_backend(mysql_session_backend &session);
~mysql_rowid_backend();
};
struct mysql_blob_backend : details::blob_backend
{
mysql_blob_backend(mysql_session_backend &session);
~mysql_blob_backend();
virtual std::size_t get_len();
virtual std::size_t read(std::size_t offset, char *buf,
std::size_t toRead);
virtual std::size_t write(std::size_t offset, char const *buf,
std::size_t toWrite);
virtual std::size_t append(char const *buf, std::size_t toWrite);
virtual void trim(std::size_t newLen);
mysql_session_backend &session_;
};
struct mysql_session_backend : details::session_backend
{
mysql_session_backend(connection_parameters const & parameters);
~mysql_session_backend();
virtual void begin();
virtual void commit();
virtual void rollback();
virtual bool get_last_insert_id(session&, std::string const&, long&);
virtual std::string get_backend_name() const { return "mysql"; }
void clean_up();
virtual mysql_statement_backend * make_statement_backend();
virtual mysql_rowid_backend * make_rowid_backend();
virtual mysql_blob_backend * make_blob_backend();
MYSQL *conn_;
};
struct mysql_backend_factory : backend_factory
{
mysql_backend_factory() {}
virtual mysql_session_backend * make_session(
connection_parameters const & parameters) const;
};
extern SOCI_MYSQL_DECL mysql_backend_factory const mysql;
extern "C"
{
// for dynamic backend loading
SOCI_MYSQL_DECL backend_factory const * factory_mysql();
SOCI_MYSQL_DECL void register_factory_mysql();
} // extern "C"
} // namespace soci
#endif // SOCI_MYSQL_H_INCLUDED

View File

@@ -0,0 +1,22 @@
//
// Copyright (C) 2015 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_NORETURN_H_INCLUDED
#define SOCI_NORETURN_H_INCLUDED
// Define a portable SOCI_NORETURN macro.
//
// TODO-C++11: Use [[noreturn]] attribute.
#if defined(__GNUC__)
# define SOCI_NORETURN __attribute__((noreturn)) void
#elif defined(_MSC_VER)
# define SOCI_NORETURN __declspec(noreturn) void
#else
# define SOCI_NORETURN void
#endif
#endif // SOCI_NORETURN_H_INCLUDED

View File

@@ -0,0 +1,455 @@
//
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney
// 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_ODBC_H_INCLUDED
#define SOCI_ODBC_H_INCLUDED
#ifdef _WIN32
# ifdef SOCI_DLL
# ifdef SOCI_ODBC_SOURCE
# define SOCI_ODBC_DECL __declspec(dllexport)
# else
# define SOCI_ODBC_DECL __declspec(dllimport)
# endif // SOCI_ODBC_SOURCE
# endif // SOCI_DLL
#endif // _WIN32
//
// If SOCI_ODBC_DECL isn't defined yet define it now
#ifndef SOCI_ODBC_DECL
# define SOCI_ODBC_DECL
#endif
#include "soci/soci-platform.h"
#include <vector>
#include <soci/soci-backend.h>
#include <sstream>
#if defined(_MSC_VER) || defined(__MINGW32__)
#include <windows.h>
#endif
#include <sqlext.h> // ODBC
#include <string.h> // strcpy()
namespace soci
{
namespace details
{
// TODO: Do we want to make it a part of public interface? --mloskot
std::size_t const odbc_max_buffer_length = 100 * 1024 * 1024;
// This cast is only used to avoid compiler warnings when passing strings
// to ODBC functions, the returned string may *not* be really modified.
inline SQLCHAR* sqlchar_cast(std::string const& s)
{
return reinterpret_cast<SQLCHAR*>(const_cast<char*>(s.c_str()));
}
}
// Option allowing to specify the "driver completion" parameter of
// SQLDriverConnect(). Its possible values are the same as the allowed values
// for this parameter in the official ODBC, i.e. one of SQL_DRIVER_XXX (in
// string form as all options are strings currently).
extern SOCI_ODBC_DECL char const * odbc_option_driver_complete;
struct odbc_statement_backend;
// Helper of into and use backends.
class odbc_standard_type_backend_base
{
protected:
odbc_standard_type_backend_base(odbc_statement_backend &st)
: statement_(st) {}
// Check if we need to pass 64 bit integers as strings to the database as
// some drivers don't support them directly.
inline bool use_string_for_bigint() const;
// If we do need to use strings for 64 bit integers, this constant defines
// the maximal string length needed.
enum
{
// This is the length of decimal representation of UINT64_MAX + 1.
max_bigint_length = 21
};
odbc_statement_backend &statement_;
private:
SOCI_NOT_COPYABLE(odbc_standard_type_backend_base)
};
struct odbc_standard_into_type_backend : details::standard_into_type_backend,
private odbc_standard_type_backend_base
{
odbc_standard_into_type_backend(odbc_statement_backend &st)
: odbc_standard_type_backend_base(st), buf_(0)
{}
virtual void define_by_pos(int &position,
void *data, details::exchange_type type);
virtual void pre_fetch();
virtual void post_fetch(bool gotData, bool calledFromFetch,
indicator *ind);
virtual void clean_up();
char *buf_; // generic buffer
void *data_;
details::exchange_type type_;
int position_;
SQLSMALLINT odbcType_;
SQLLEN valueLen_;
private:
SOCI_NOT_COPYABLE(odbc_standard_into_type_backend)
};
struct odbc_vector_into_type_backend : details::vector_into_type_backend,
private odbc_standard_type_backend_base
{
odbc_vector_into_type_backend(odbc_statement_backend &st)
: odbc_standard_type_backend_base(st), indHolders_(NULL),
data_(NULL), buf_(NULL) {}
virtual void define_by_pos(int &position,
void *data, details::exchange_type type);
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 void clean_up();
// helper function for preparing indicators
// (as part of the define_by_pos)
void prepare_indicators(std::size_t size);
SQLLEN *indHolders_;
std::vector<SQLLEN> indHolderVec_;
void *data_;
char *buf_; // generic buffer
details::exchange_type type_;
std::size_t colSize_; // size of the string column (used for strings)
SQLSMALLINT odbcType_;
};
struct odbc_standard_use_type_backend : details::standard_use_type_backend,
private odbc_standard_type_backend_base
{
odbc_standard_use_type_backend(odbc_statement_backend &st)
: odbc_standard_type_backend_base(st),
position_(-1), data_(0), buf_(0), indHolder_(0) {}
virtual void bind_by_pos(int &position,
void *data, details::exchange_type type, bool readOnly);
virtual void bind_by_name(std::string const &name,
void *data, details::exchange_type type, bool readOnly);
virtual void pre_use(indicator const *ind);
virtual void post_use(bool gotData, indicator *ind);
virtual void clean_up();
// Return the pointer to the buffer containing data to be used by ODBC.
// This can be either data_ itself or buf_, that is allocated by this
// function if necessary.
//
// Also fill in the size of the data and SQL and C types of it.
void* prepare_for_bind(SQLLEN &size,
SQLSMALLINT &sqlType, SQLSMALLINT &cType);
int position_;
void *data_;
details::exchange_type type_;
char *buf_;
SQLLEN indHolder_;
};
struct odbc_vector_use_type_backend : details::vector_use_type_backend,
private odbc_standard_type_backend_base
{
odbc_vector_use_type_backend(odbc_statement_backend &st)
: odbc_standard_type_backend_base(st), indHolders_(NULL),
data_(NULL), buf_(NULL) {}
// helper function for preparing indicators
// (as part of the define_by_pos)
void prepare_indicators(std::size_t size);
// common part for bind_by_pos and bind_by_name
void prepare_for_bind(void *&data, SQLUINTEGER &size, SQLSMALLINT &sqlType, SQLSMALLINT &cType);
void bind_helper(int &position,
void *data, details::exchange_type type);
virtual void bind_by_pos(int &position,
void *data, details::exchange_type type);
virtual void bind_by_name(std::string const &name,
void *data, details::exchange_type type);
virtual void pre_use(indicator const *ind);
virtual std::size_t size();
virtual void clean_up();
SQLLEN *indHolders_;
std::vector<SQLLEN> indHolderVec_;
void *data_;
details::exchange_type type_;
char *buf_; // generic buffer
std::size_t colSize_; // size of the string column (used for strings)
// used for strings only
std::size_t maxSize_;
};
struct odbc_session_backend;
struct odbc_statement_backend : details::statement_backend
{
odbc_statement_backend(odbc_session_backend &session);
virtual void alloc();
virtual void clean_up();
virtual void prepare(std::string const &query,
details::statement_type eType);
virtual exec_fetch_result execute(int number);
virtual exec_fetch_result fetch(int number);
virtual long long get_affected_rows();
virtual int get_number_of_rows();
virtual std::string get_parameter_name(int index) const;
virtual std::string rewrite_for_procedure_call(std::string const &query);
virtual int prepare_for_describe();
virtual void describe_column(int colNum, data_type &dtype,
std::string &columnName);
// helper for defining into vector<string>
std::size_t column_size(int position);
virtual odbc_standard_into_type_backend * make_into_type_backend();
virtual odbc_standard_use_type_backend * make_use_type_backend();
virtual odbc_vector_into_type_backend * make_vector_into_type_backend();
virtual odbc_vector_use_type_backend * make_vector_use_type_backend();
odbc_session_backend &session_;
SQLHSTMT hstmt_;
SQLULEN numRowsFetched_;
bool hasVectorUseElements_;
bool boundByName_;
bool boundByPos_;
long long rowsAffected_; // number of rows affected by the last operation
std::string query_;
std::vector<std::string> names_; // list of names for named binds
};
struct odbc_rowid_backend : details::rowid_backend
{
odbc_rowid_backend(odbc_session_backend &session);
~odbc_rowid_backend();
};
struct odbc_blob_backend : details::blob_backend
{
odbc_blob_backend(odbc_session_backend &session);
~odbc_blob_backend();
virtual std::size_t get_len();
virtual std::size_t read(std::size_t offset, char *buf,
std::size_t toRead);
virtual std::size_t write(std::size_t offset, char const *buf,
std::size_t toWrite);
virtual std::size_t append(char const *buf, std::size_t toWrite);
virtual void trim(std::size_t newLen);
odbc_session_backend &session_;
};
struct odbc_session_backend : details::session_backend
{
odbc_session_backend(connection_parameters const & parameters);
~odbc_session_backend();
virtual void begin();
virtual void commit();
virtual void rollback();
virtual bool get_next_sequence_value(session & s,
std::string const & sequence, long & value);
virtual bool get_last_insert_id(session & s,
std::string const & table, long & value);
virtual std::string get_backend_name() const { return "odbc"; }
void configure_connection();
void reset_transaction();
void clean_up();
virtual odbc_statement_backend * make_statement_backend();
virtual odbc_rowid_backend * make_rowid_backend();
virtual odbc_blob_backend * make_blob_backend();
enum database_product
{
prod_uninitialized, // Never returned by get_database_product().
prod_firebird,
prod_mssql,
prod_mysql,
prod_oracle,
prod_postgresql,
prod_sqlite,
prod_unknown = -1
};
// Determine the type of the database we're connected to.
database_product get_database_product();
// Return full ODBC connection string.
std::string get_connection_string() const { return connection_string_; }
SQLHENV henv_;
SQLHDBC hdbc_;
std::string connection_string_;
database_product product_;
};
class SOCI_ODBC_DECL odbc_soci_error : public soci_error
{
SQLCHAR message_[SQL_MAX_MESSAGE_LENGTH + 1];
SQLCHAR sqlstate_[SQL_SQLSTATE_SIZE + 1];
SQLINTEGER sqlcode_;
public:
odbc_soci_error(SQLSMALLINT htype,
SQLHANDLE hndl,
std::string const & msg)
: soci_error(interpret_odbc_error(htype, hndl, msg))
{
}
SQLCHAR const * odbc_error_code() const
{
return sqlstate_;
}
SQLINTEGER native_error_code() const
{
return sqlcode_;
}
SQLCHAR const * odbc_error_message() const
{
return message_;
}
private:
std::string interpret_odbc_error(SQLSMALLINT htype, SQLHANDLE hndl, std::string const& msg)
{
const char* socierror = NULL;
SQLSMALLINT length, i = 1;
switch ( SQLGetDiagRecA(htype, hndl, i, sqlstate_, &sqlcode_,
message_, SQL_MAX_MESSAGE_LENGTH + 1,
&length) )
{
case SQL_SUCCESS:
// The error message was successfully retrieved.
break;
case SQL_INVALID_HANDLE:
socierror = "[SOCI]: Invalid handle.";
break;
case SQL_ERROR:
socierror = "[SOCI]: SQLGetDiagRec() error.";
break;
case SQL_SUCCESS_WITH_INFO:
socierror = "[SOCI]: Error message too long.";
break;
case SQL_NO_DATA:
socierror = "[SOCI]: No error.";
break;
default:
socierror = "[SOCI]: Unexpected SQLGetDiagRec() return value.";
break;
}
if (socierror)
{
// Use our own error message if we failed to retrieve the ODBC one.
strcpy(reinterpret_cast<char*>(message_), socierror);
// Use "General warning" SQLSTATE code.
strcpy(reinterpret_cast<char*>(sqlstate_), "01000");
sqlcode_ = 0;
}
std::ostringstream ss;
ss << "Error " << msg << ": " << message_ << " (SQL state " << sqlstate_ << ")";
return ss.str();
}
};
inline bool is_odbc_error(SQLRETURN rc)
{
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA)
{
return true;
}
else
{
return false;
}
}
inline bool odbc_standard_type_backend_base::use_string_for_bigint() const
{
// Oracle ODBC driver doesn't support SQL_C_[SU]BIGINT data types
// (see appendix G.1 of Oracle Database Administrator's reference at
// http://docs.oracle.com/cd/B19306_01/server.102/b15658/app_odbc.htm),
// so we need a special workaround for this case and we represent 64
// bit integers as strings and rely on ODBC driver for transforming
// them to SQL_NUMERIC.
return statement_.session_.get_database_product()
== odbc_session_backend::prod_oracle;
}
struct odbc_backend_factory : backend_factory
{
odbc_backend_factory() {}
virtual odbc_session_backend * make_session(
connection_parameters const & parameters) const;
};
extern SOCI_ODBC_DECL odbc_backend_factory const odbc;
extern "C"
{
// for dynamic backend loading
SOCI_ODBC_DECL backend_factory const * factory_odbc();
SOCI_ODBC_DECL void register_factory_odbc();
} // extern "C"
} // namespace soci
#endif // SOCI_EMPTY_H_INCLUDED

View File

@@ -0,0 +1,119 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_ONCE_TEMP_TYPE_H_INCLUDED
#define SOCI_ONCE_TEMP_TYPE_H_INCLUDED
#include "soci/ref-counted-statement.h"
#include "soci/prepare-temp-type.h"
#if __cplusplus >= 201103L
#define SOCI_ONCE_TEMP_TYPE_NOEXCEPT noexcept(false)
#else
#define SOCI_ONCE_TEMP_TYPE_NOEXCEPT
#endif
namespace soci
{
class session;
namespace details
{
class ref_counted_statement;
// this needs to be lightweight and copyable
class SOCI_DECL once_temp_type
{
public:
once_temp_type(session & s);
once_temp_type(once_temp_type const & o);
once_temp_type & operator=(once_temp_type const & o);
~once_temp_type() SOCI_ONCE_TEMP_TYPE_NOEXCEPT;
template <typename T>
once_temp_type & operator<<(T const & t)
{
rcst_->accumulate(t);
return *this;
}
once_temp_type & operator,(into_type_ptr const &);
template <typename T, typename Indicator>
once_temp_type &operator,(into_container<T, Indicator> const &ic)
{
rcst_->exchange(ic);
return *this;
}
template <typename T, typename Indicator>
once_temp_type &operator,(use_container<T, Indicator> const &uc)
{
rcst_->exchange(uc);
return *this;
}
private:
ref_counted_statement * rcst_;
};
// this needs to be lightweight and copyable
class once_type
{
public:
once_type() : session_(NULL) {}
once_type(session * s) : session_(s) {}
void set_session(session * s)
{
session_ = s;
}
template <typename T>
once_temp_type operator<<(T const & t)
{
once_temp_type o(*session_);
o << t;
return o;
}
private:
session * session_;
};
// this needs to be lightweight and copyable
class prepare_type
{
public:
prepare_type() : session_(NULL) {}
prepare_type(session * s) : session_(s) {}
void set_session(session * s)
{
session_ = s;
}
template <typename T>
prepare_temp_type operator<<(T const & t)
{
prepare_temp_type p(*session_);
p << t;
return p;
}
private:
session * session_;
};
} // namespace details
} // namespace soci
#endif

View File

@@ -0,0 +1,301 @@
//
// Copyright (C) 2004-2007 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)
//
#ifndef SOCI_ORACLE_H_INCLUDED
#define SOCI_ORACLE_H_INCLUDED
#ifdef _WIN32
# ifdef SOCI_DLL
# ifdef SOCI_ORACLE_SOURCE
# define SOCI_ORACLE_DECL __declspec(dllexport)
# else
# define SOCI_ORACLE_DECL __declspec(dllimport)
# endif // SOCI_ORACLE_SOURCE
# endif // SOCI_DLL
#endif // _WIN32
//
// If SOCI_ORACLE_DECL isn't defined yet define it now
#ifndef SOCI_ORACLE_DECL
# define SOCI_ORACLE_DECL
#endif
#include <soci/soci-backend.h>
#include <oci.h> // OCI
#include <vector>
#ifdef _MSC_VER
#pragma warning(disable:4512 4511)
#endif
namespace soci
{
class SOCI_ORACLE_DECL oracle_soci_error : public soci_error
{
public:
oracle_soci_error(std::string const & msg, int errNum = 0);
int err_num_;
};
struct oracle_statement_backend;
struct oracle_standard_into_type_backend : details::standard_into_type_backend
{
oracle_standard_into_type_backend(oracle_statement_backend &st)
: statement_(st), defnp_(NULL), indOCIHolder_(0),
data_(NULL), buf_(NULL) {}
virtual void define_by_pos(int &position,
void *data, details::exchange_type type);
virtual void pre_fetch();
virtual void post_fetch(bool gotData, bool calledFromFetch,
indicator *ind);
virtual void clean_up();
oracle_statement_backend &statement_;
OCIDefine *defnp_;
sb2 indOCIHolder_;
void *data_;
char *buf_; // generic buffer
details::exchange_type type_;
ub2 rCode_;
};
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) {}
virtual void define_by_pos(int &position,
void *data, details::exchange_type type);
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 void clean_up();
// helper function for preparing indicators and sizes_ vectors
// (as part of the define_by_pos)
void prepare_indicators(std::size_t size);
oracle_statement_backend &statement_;
OCIDefine *defnp_;
sb2 *indOCIHolders_;
std::vector<sb2> indOCIHolderVec_;
void *data_;
char *buf_; // generic buffer
details::exchange_type type_;
std::size_t colSize_; // size of the string column (used for strings)
std::vector<ub2> sizes_; // sizes of data fetched (used for strings)
std::vector<ub2> rCodes_;
};
struct oracle_standard_use_type_backend : details::standard_use_type_backend
{
oracle_standard_use_type_backend(oracle_statement_backend &st)
: statement_(st), bindp_(NULL), indOCIHolder_(0),
data_(NULL), buf_(NULL) {}
virtual void bind_by_pos(int &position,
void *data, details::exchange_type type, bool readOnly);
virtual void bind_by_name(std::string const &name,
void *data, details::exchange_type type, bool readOnly);
// common part for bind_by_pos and bind_by_name
void prepare_for_bind(void *&data, sb4 &size, ub2 &oracleType, bool readOnly);
virtual void pre_use(indicator const *ind);
virtual void post_use(bool gotData, indicator *ind);
virtual void clean_up();
oracle_statement_backend &statement_;
OCIBind *bindp_;
sb2 indOCIHolder_;
void *data_;
bool readOnly_;
char *buf_; // generic buffer
details::exchange_type type_;
};
struct oracle_vector_use_type_backend : details::vector_use_type_backend
{
oracle_vector_use_type_backend(oracle_statement_backend &st)
: 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_name(std::string const &name,
void *data, details::exchange_type type);
// common part for bind_by_pos and bind_by_name
void prepare_for_bind(void *&data, sb4 &size, ub2 &oracleType);
// helper function for preparing indicators and sizes_ vectors
// (as part of the bind_by_pos and bind_by_name)
void prepare_indicators(std::size_t size);
virtual void pre_use(indicator const *ind);
virtual std::size_t size();
virtual void clean_up();
oracle_statement_backend &statement_;
OCIBind *bindp_;
std::vector<sb2> indOCIHolderVec_;
sb2 *indOCIHolders_;
void *data_;
char *buf_; // generic buffer
details::exchange_type type_;
// used for strings only
std::vector<ub2> sizes_;
std::size_t maxSize_;
};
struct oracle_session_backend;
struct oracle_statement_backend : details::statement_backend
{
oracle_statement_backend(oracle_session_backend &session);
virtual void alloc();
virtual void clean_up();
virtual void prepare(std::string const &query,
details::statement_type eType);
virtual exec_fetch_result execute(int number);
virtual exec_fetch_result fetch(int number);
virtual long long get_affected_rows();
virtual int get_number_of_rows();
virtual std::string get_parameter_name(int index) const;
virtual std::string rewrite_for_procedure_call(std::string const &query);
virtual int prepare_for_describe();
virtual void describe_column(int colNum, data_type &dtype,
std::string &columnName);
// helper for defining into vector<string>
std::size_t column_size(int position);
virtual oracle_standard_into_type_backend * make_into_type_backend();
virtual oracle_standard_use_type_backend * make_use_type_backend();
virtual oracle_vector_into_type_backend * make_vector_into_type_backend();
virtual oracle_vector_use_type_backend * make_vector_use_type_backend();
oracle_session_backend &session_;
OCIStmt *stmtp_;
bool boundByName_;
bool boundByPos_;
bool noData_;
};
struct oracle_rowid_backend : details::rowid_backend
{
oracle_rowid_backend(oracle_session_backend &session);
~oracle_rowid_backend();
OCIRowid *rowidp_;
};
struct oracle_blob_backend : details::blob_backend
{
oracle_blob_backend(oracle_session_backend &session);
~oracle_blob_backend();
virtual std::size_t get_len();
virtual std::size_t read(std::size_t offset, char *buf,
std::size_t toRead);
virtual std::size_t write(std::size_t offset, char const *buf,
std::size_t toWrite);
virtual std::size_t append(char const *buf, std::size_t toWrite);
virtual void trim(std::size_t newLen);
oracle_session_backend &session_;
OCILobLocator *lobp_;
};
struct oracle_session_backend : details::session_backend
{
oracle_session_backend(std::string const & serviceName,
std::string const & userName,
std::string const & password,
int mode,
bool decimals_as_strings = false);
~oracle_session_backend();
virtual void begin();
virtual void commit();
virtual void rollback();
virtual std::string get_backend_name() const { return "oracle"; }
void clean_up();
virtual oracle_statement_backend * make_statement_backend();
virtual oracle_rowid_backend * make_rowid_backend();
virtual oracle_blob_backend * make_blob_backend();
bool get_option_decimals_as_strings() { return decimals_as_strings_; }
// Return either SQLT_FLT or SQLT_BDOUBLE as the type to use when binding
// values of C type "double" (the latter is preferable but might not be
// always available).
ub2 get_double_sql_type() const;
OCIEnv *envhp_;
OCIServer *srvhp_;
OCIError *errhp_;
OCISvcCtx *svchp_;
OCISession *usrhp_;
bool decimals_as_strings_;
};
struct oracle_backend_factory : backend_factory
{
oracle_backend_factory() {}
virtual oracle_session_backend * make_session(
connection_parameters const & parameters) const;
};
extern SOCI_ORACLE_DECL oracle_backend_factory const oracle;
extern "C"
{
// for dynamic backend loading
SOCI_ORACLE_DECL backend_factory const * factory_oracle();
SOCI_ORACLE_DECL void register_factory_oracle();
} // extern "C"
} // namespace soci
#endif

View File

@@ -0,0 +1,352 @@
//
// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
// Copyright (C) 2011 Gevorg Voskanyan
// 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_POSTGRESQL_H_INCLUDED
#define SOCI_POSTGRESQL_H_INCLUDED
#ifdef _WIN32
# ifdef SOCI_DLL
# ifdef SOCI_POSTGRESQL_SOURCE
# define SOCI_POSTGRESQL_DECL __declspec(dllexport)
# else
# define SOCI_POSTGRESQL_DECL __declspec(dllimport)
# endif // SOCI_POSTGRESQL_SOURCE
# endif // SOCI_DLL
#endif // _WIN32
//
// If SOCI_POSTGRESQL_DECL isn't defined yet define it now
#ifndef SOCI_POSTGRESQL_DECL
# define SOCI_POSTGRESQL_DECL
#endif
#include <soci/soci-backend.h>
#include <libpq-fe.h>
#include <vector>
namespace soci
{
class postgresql_soci_error : public soci_error
{
public:
postgresql_soci_error(std::string const & msg, char const * sqlst);
std::string sqlstate() const;
private:
char sqlstate_[ 5 ]; // not std::string to keep copy-constructor no-throw
};
namespace details
{
// A class thinly encapsulating PGresult. Its main purpose is to ensure that
// PQclear() is always called, avoiding result memory leaks.
class postgresql_result
{
public:
// Creates a wrapper for the given, possibly NULL, result. The wrapper
// object takes ownership of the object and will call PQclear() on it.
explicit postgresql_result(PGresult* result = NULL)
{
init(result);
}
// Frees any currently stored result pointer and takes ownership of the
// given one.
void reset(PGresult* result = NULL)
{
free();
init(result);
}
// Check whether the status is PGRES_COMMAND_OK and throw an exception if
// it is different. Notice that if the query can return any results,
// check_for_data() below should be used instead to verify whether anything
// was returned or not.
//
// The provided error message is used only for the exception being thrown
// and should describe the operation which yielded this result.
void check_for_errors(char const* errMsg) const;
// Check whether the status indicates successful query completion, either
// with the return results (in which case true is returned) or without them
// (then false is returned). If the status corresponds to an error, throws
// an exception, just as check_for_errors().
bool check_for_data(char const* errMsg) const;
// Implicit conversion to const PGresult: this is somewhat dangerous but
// allows us to avoid changing the existing code that uses PGresult and
// avoids the really bad problem with calling PQclear() twice accidentally
// as this would require a conversion to non-const pointer that we do not
// provide.
operator const PGresult*() const { return result_; }
// Get the associated result (which may be NULL). Unlike the implicit
// conversion above, this one returns a non-const pointer, so you should be
// careful to avoid really modifying it.
PGresult* get_result() const { return result_; }
// Dtor frees the result.
~postgresql_result() { free(); }
private:
void init(PGresult* result)
{
result_ = result;
}
void free()
{
// Notice that it is safe to call PQclear() with NULL pointer, it
// simply does nothing in this case.
PQclear(result_);
}
PGresult* result_;
SOCI_NOT_COPYABLE(postgresql_result)
};
} // namespace details
struct postgresql_statement_backend;
struct postgresql_standard_into_type_backend : details::standard_into_type_backend
{
postgresql_standard_into_type_backend(postgresql_statement_backend & st)
: statement_(st) {}
virtual void define_by_pos(int & position,
void * data, details::exchange_type type);
virtual void pre_fetch();
virtual void post_fetch(bool gotData, bool calledFromFetch,
indicator * ind);
virtual void clean_up();
postgresql_statement_backend & statement_;
void * data_;
details::exchange_type type_;
int position_;
};
struct postgresql_vector_into_type_backend : details::vector_into_type_backend
{
postgresql_vector_into_type_backend(postgresql_statement_backend & st)
: statement_(st) {}
virtual void define_by_pos(int & position,
void * data, details::exchange_type type);
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 void clean_up();
postgresql_statement_backend & statement_;
void * data_;
details::exchange_type type_;
int position_;
};
struct postgresql_standard_use_type_backend : details::standard_use_type_backend
{
postgresql_standard_use_type_backend(postgresql_statement_backend & st)
: statement_(st), position_(0), buf_(NULL) {}
virtual void bind_by_pos(int & position,
void * data, details::exchange_type type, bool readOnly);
virtual void bind_by_name(std::string const & name,
void * data, details::exchange_type type, bool readOnly);
virtual void pre_use(indicator const * ind);
virtual void post_use(bool gotData, indicator * ind);
virtual void clean_up();
postgresql_statement_backend & statement_;
void * data_;
details::exchange_type type_;
int position_;
std::string name_;
char * buf_;
};
struct postgresql_vector_use_type_backend : details::vector_use_type_backend
{
postgresql_vector_use_type_backend(postgresql_statement_backend & st)
: statement_(st), position_(0) {}
virtual void bind_by_pos(int & position,
void * data, details::exchange_type type);
virtual void bind_by_name(std::string const & name,
void * data, details::exchange_type type);
virtual void pre_use(indicator const * ind);
virtual std::size_t size();
virtual void clean_up();
postgresql_statement_backend & statement_;
void * data_;
details::exchange_type type_;
int position_;
std::string name_;
std::vector<char *> buffers_;
};
struct postgresql_session_backend;
struct postgresql_statement_backend : details::statement_backend
{
postgresql_statement_backend(postgresql_session_backend & session);
~postgresql_statement_backend();
virtual void alloc();
virtual void clean_up();
virtual void prepare(std::string const & query,
details::statement_type stType);
virtual exec_fetch_result execute(int number);
virtual exec_fetch_result fetch(int number);
virtual long long get_affected_rows();
virtual int get_number_of_rows();
virtual std::string get_parameter_name(int index) const;
virtual std::string rewrite_for_procedure_call(std::string const & query);
virtual int prepare_for_describe();
virtual void describe_column(int colNum, data_type & dtype,
std::string & columnName);
virtual postgresql_standard_into_type_backend * make_into_type_backend();
virtual postgresql_standard_use_type_backend * make_use_type_backend();
virtual postgresql_vector_into_type_backend * make_vector_into_type_backend();
virtual postgresql_vector_use_type_backend * make_vector_use_type_backend();
postgresql_session_backend & session_;
details::postgresql_result result_;
std::string query_;
details::statement_type stType_;
std::string statementName_;
std::vector<std::string> names_; // list of names for named binds
long long rowsAffectedBulk_; // number of rows affected by the last bulk operation
int numberOfRows_; // number of rows retrieved from the server
int currentRow_; // "current" row number to consume in postFetch
int rowsToConsume_; // number of rows to be consumed in postFetch
bool justDescribed_; // to optimize row description with immediately
// following actual statement execution
bool hasIntoElements_;
bool hasVectorIntoElements_;
bool hasUseElements_;
bool hasVectorUseElements_;
// the following maps are used for finding data buffers according to
// use elements specified by the user
typedef std::map<int, char **> UseByPosBuffersMap;
UseByPosBuffersMap useByPosBuffers_;
typedef std::map<std::string, char **> UseByNameBuffersMap;
UseByNameBuffersMap useByNameBuffers_;
};
struct postgresql_rowid_backend : details::rowid_backend
{
postgresql_rowid_backend(postgresql_session_backend & session);
~postgresql_rowid_backend();
unsigned long value_;
};
struct postgresql_blob_backend : details::blob_backend
{
postgresql_blob_backend(postgresql_session_backend & session);
~postgresql_blob_backend();
virtual std::size_t get_len();
virtual std::size_t read(std::size_t offset, char * buf,
std::size_t toRead);
virtual std::size_t write(std::size_t offset, char const * buf,
std::size_t toWrite);
virtual std::size_t append(char const * buf, std::size_t toWrite);
virtual void trim(std::size_t newLen);
postgresql_session_backend & session_;
unsigned long oid_; // oid of the large object
int fd_; // descriptor of the large object
};
struct postgresql_session_backend : details::session_backend
{
postgresql_session_backend(connection_parameters const & parameters);
~postgresql_session_backend();
virtual void begin();
virtual void commit();
virtual void rollback();
void deallocate_prepared_statement(const std::string & statementName);
virtual bool get_next_sequence_value(session & s,
std::string const & sequence, long & value);
virtual std::string get_backend_name() const { return "postgresql"; }
void clean_up();
virtual postgresql_statement_backend * make_statement_backend();
virtual postgresql_rowid_backend * make_rowid_backend();
virtual postgresql_blob_backend * make_blob_backend();
std::string get_next_statement_name();
int statementCount_;
PGconn * conn_;
};
struct postgresql_backend_factory : backend_factory
{
postgresql_backend_factory() {}
virtual postgresql_session_backend * make_session(
connection_parameters const & parameters) const;
};
extern SOCI_POSTGRESQL_DECL postgresql_backend_factory const postgresql;
extern "C"
{
// for dynamic backend loading
SOCI_POSTGRESQL_DECL backend_factory const * factory_postgresql();
SOCI_POSTGRESQL_DECL void register_factory_postgresql();
} // extern "C"
} // namespace soci
#endif // SOCI_POSTGRESQL_H_INCLUDED

View File

@@ -0,0 +1,65 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_PREPARE_TEMP_TYPE_INCLUDED
#define SOCI_PREPARE_TEMP_TYPE_INCLUDED
#include "soci/into-type.h"
#include "soci/use-type.h"
#include "soci/use.h"
#include "soci/ref-counted-prepare-info.h"
namespace soci
{
namespace details
{
// this needs to be lightweight and copyable
class SOCI_DECL prepare_temp_type
{
public:
prepare_temp_type(session &);
prepare_temp_type(prepare_temp_type const &);
prepare_temp_type & operator=(prepare_temp_type const &);
~prepare_temp_type();
template <typename T>
prepare_temp_type & operator<<(T const & t)
{
rcpi_->accumulate(t);
return *this;
}
prepare_temp_type & operator,(into_type_ptr const & i);
template <typename T, typename Indicator>
prepare_temp_type &operator,(into_container<T, Indicator> const &ic)
{
rcpi_->exchange(ic);
return *this;
}
template <typename T, typename Indicator>
prepare_temp_type &operator,(use_container<T, Indicator> const &uc)
{
rcpi_->exchange(uc);
return *this;
}
ref_counted_prepare_info * get_prepare_info() const { return rcpi_; }
private:
ref_counted_prepare_info * rcpi_;
};
} // namespace details
} // namespace soci
#endif

View File

@@ -0,0 +1,89 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_PROCEDURE_H_INCLUDED
#define SOCI_PROCEDURE_H_INCLUDED
#include "soci/statement.h"
namespace soci
{
namespace details
{
class SOCI_DECL procedure_impl : public statement_impl
{
public:
procedure_impl(session & s) : statement_impl(s), refCount_(1) {}
procedure_impl(prepare_temp_type const & prep);
void inc_ref() { ++refCount_; }
void dec_ref()
{
if (--refCount_ == 0)
{
delete this;
}
}
private:
int refCount_;
};
} // namespace details
class SOCI_DECL procedure
{
public:
// this is a conversion constructor
procedure(details::prepare_temp_type const & prep)
: impl_(new details::procedure_impl(prep)) {}
~procedure() { impl_->dec_ref(); }
// copy is supported here
procedure(procedure const & other)
: impl_(other.impl_)
{
impl_->inc_ref();
}
void operator=(procedure const & other)
{
other.impl_->inc_ref();
impl_->dec_ref();
impl_ = other.impl_;
}
// forwarders to procedure_impl
// (or rather to its base interface from statement_impl)
bool execute(bool withDataExchange = false)
{
gotData_ = impl_->execute(withDataExchange);
return gotData_;
}
bool fetch()
{
gotData_ = impl_->fetch();
return gotData_;
}
bool got_data() const
{
return gotData_;
}
private:
details::procedure_impl * impl_;
bool gotData_;
};
} // namespace soci
#endif

View File

@@ -0,0 +1,59 @@
//
// Copyright (C) 2013 Mateusz Loskot <mateusz@loskot.net>
// 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_QUERY_TRANSFORMATION_H_INCLUDED
#define SOCI_QUERY_TRANSFORMATION_H_INCLUDED
#include "soci/soci-platform.h"
#include <functional>
#include <string>
namespace soci
{
namespace details
{
// Query transformation is a mechanism that enables user to apply
// any string-to-string transformation to SQL statement just
// before it is executed.
// Transformation procedure is specified by user,
// be it a function or an arbitrary type as long as it
// defines operator() with the appropriate signature:
// unary function takes any type converible-to std::string
// and returns std::string.
class query_transformation_function
: public std::unary_function<std::string const&, std::string>
{
public:
virtual ~query_transformation_function() {}
virtual result_type operator()(argument_type a) const = 0;
};
template <typename T>
class query_transformation : public query_transformation_function
{
public:
query_transformation(T callback)
: callback_(callback)
{}
result_type operator()(argument_type query) const
{
return callback_(query);
}
private:
T callback_;
};
} // namespace details
} // namespace soci
#endif // SOCI_QUERY_TRANSFORMATION_H_INCLUDED

View File

@@ -0,0 +1,66 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_REF_COUNTED_PREPARE_INFO_INCLUDED
#define SOCI_REF_COUNTED_PREPARE_INFO_INCLUDED
#include "soci/bind-values.h"
#include "soci/ref-counted-statement.h"
// std
#include <string>
#include <vector>
namespace soci
{
class session;
namespace details
{
class procedure_impl;
class statement_impl;
class into_type_base;
// this class conveys only the statement text and the bind/define info
// it exists only to be passed to statement's constructor
class ref_counted_prepare_info : public ref_counted_statement_base
{
public:
ref_counted_prepare_info(session& s)
: ref_counted_statement_base(s)
{}
void exchange(use_type_ptr const& u) { uses_.exchange(u); }
template <typename T, typename Indicator>
void exchange(use_container<T, Indicator> const &uc)
{ uses_.exchange(uc); }
void exchange(into_type_ptr const& i) { intos_.exchange(i); }
template <typename T, typename Indicator>
void exchange(into_container<T, Indicator> const &ic)
{ intos_.exchange(ic); }
void final_action();
private:
friend class statement_impl;
friend class procedure_impl;
into_type_vector intos_;
use_type_vector uses_;
std::string get_query() const;
};
} // namespace details
} // namespace soci
#endif

View File

@@ -0,0 +1,89 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_REF_COUNTED_STATEMENT_H_INCLUDED
#define SOCI_REF_COUNTED_STATEMENT_H_INCLUDED
#include "soci/statement.h"
#include "soci/into-type.h"
#include "soci/use-type.h"
// std
#include <sstream>
namespace soci
{
namespace details
{
// this class is a base for both "once" and "prepare" statements
class SOCI_DECL ref_counted_statement_base
{
public:
ref_counted_statement_base(session& s);
virtual ~ref_counted_statement_base() {}
virtual void final_action() = 0;
void inc_ref() { ++refCount_; }
void dec_ref()
{
if (--refCount_ == 0)
{
try
{
final_action();
}
catch (...)
{
delete this;
throw;
}
delete this;
}
}
template <typename T>
void accumulate(T const & t) { get_query_stream() << t; }
protected:
// this function allows to break the circular dependenc
// between session and this class
std::ostringstream & get_query_stream();
int refCount_;
session & session_;
private:
SOCI_NOT_COPYABLE(ref_counted_statement_base)
};
// this class is supposed to be a vehicle for the "once" statements
// it executes the whole statement in its destructor
class ref_counted_statement : public ref_counted_statement_base
{
public:
ref_counted_statement(session & s)
: ref_counted_statement_base(s), st_(s) {}
virtual void final_action();
template <typename T>
void exchange(T &t) { st_.exchange(t); }
private:
statement st_;
};
} // namespace details
} // namespace soci
#endif

View File

@@ -0,0 +1,79 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_INTO_ROW_H_INCLUDED
#define SOCI_INTO_ROW_H_INCLUDED
#include "soci/into-type.h"
#include "soci/exchange-traits.h"
#include "soci/row.h"
#include "soci/statement.h"
// std
#include <cstddef>
namespace soci
{
namespace details
{
// Support selecting into a row for dynamic queries
template <>
class into_type<row>
: public into_type_base // bypass the standard_into_type
{
public:
into_type(row & r) : r_(r) {}
into_type(row & r, indicator &) : r_(r) {}
private:
// special handling for Row
virtual void define(statement_impl & st, int & /* position */)
{
st.set_row(&r_);
// actual row description is performed
// as part of the statement execute
}
virtual void pre_fetch() {}
virtual void post_fetch(bool gotData, bool /* calledFromFetch */)
{
r_.reset_get_counter();
if (gotData)
{
// this is used only to re-dispatch to derived class, if any
// (the derived class might be generated automatically by
// user conversions)
convert_from_base();
}
}
virtual void clean_up() {}
virtual std::size_t size() const { return 1; }
virtual void convert_from_base() {}
row & r_;
SOCI_NOT_COPYABLE(into_type)
};
template <>
struct exchange_traits<row>
{
typedef basic_type_tag type_family;
};
} // namespace details
} // namespace soci
#endif

140
src/soci/include/soci/row.h Normal file
View File

@@ -0,0 +1,140 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_ROW_H_INCLUDED
#define SOCI_ROW_H_INCLUDED
#include "soci/type-holder.h"
#include "soci/soci-backend.h"
#include "soci/type-conversion.h"
// std
#include <cstddef>
#include <map>
#include <string>
#include <vector>
namespace soci
{
class SOCI_DECL column_properties
{
// use getters/setters in case we want to make some
// of the getters lazy in the future
public:
std::string get_name() const { return name_; }
data_type get_data_type() const { return dataType_; }
void set_name(std::string const& name) { name_ = name; }
void set_data_type(data_type dataType) { dataType_ = dataType; }
private:
std::string name_;
data_type dataType_;
};
class SOCI_DECL row
{
public:
row();
~row();
void uppercase_column_names(bool forceToUpper);
void add_properties(column_properties const& cp);
std::size_t size() const;
void clean_up();
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)
{
holders_.push_back(new details::type_holder<T>(t));
indicators_.push_back(ind);
}
column_properties const& get_properties(std::size_t pos) const;
column_properties const& get_properties(std::string const& name) const;
template <typename T>
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>();
T ret;
type_conversion<T>::from_base(baseVal, *indicators_.at(pos), ret);
return ret;
}
template <typename T>
T get(std::size_t pos, T const &nullValue) const
{
if (i_null == *indicators_.at(pos))
{
return nullValue;
}
return get<T>(pos);
}
template <typename T>
T get(std::string const &name) const
{
std::size_t const pos = find_column(name);
return get<T>(pos);
}
template <typename T>
T get(std::string const &name, T const &nullValue) const
{
std::size_t const pos = find_column(name);
if (i_null == *indicators_[pos])
{
return nullValue;
}
return get<T>(pos);
}
template <typename T>
row const& operator>>(T& value) const
{
value = get<T>(currentPos_);
++currentPos_;
return *this;
}
void skip(std::size_t num = 1) const
{
currentPos_ += num;
}
void reset_get_counter() const
{
currentPos_ = 0;
}
private:
SOCI_NOT_COPYABLE(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_;
bool uppercaseColumnNames_;
mutable std::size_t currentPos_;
};
} // namespace soci
#endif // SOCI_ROW_H_INCLUDED

View File

@@ -0,0 +1,59 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_ROWID_EXCHANGE_H_INCLUDED
#define SOCI_ROWID_EXCHANGE_H_INCLUDED
#include "soci/rowid.h"
#include "soci/into-type.h"
#include "soci/use-type.h"
#include "soci/exchange-traits.h"
// std
#include <string>
namespace soci
{
namespace details
{
template <>
class use_type<rowid> : public standard_use_type
{
public:
use_type(rowid & rid, std::string const & name = std::string())
: standard_use_type(&rid, x_rowid, false, name) {}
use_type(rowid const & rid, std::string const & name = std::string())
: standard_use_type(const_cast<rowid *>(&rid), x_rowid, true, name) {}
use_type(rowid & rid, indicator & ind,
std::string const & name = std::string())
: standard_use_type(&rid, x_rowid, ind, false, name) {}
use_type(rowid const & rid, indicator & ind,
std::string const & name = std::string())
: standard_use_type(const_cast<rowid *>(&rid), x_rowid, ind, true, name) {}
};
template <>
class into_type<rowid> : public standard_into_type
{
public:
into_type(rowid & rid) : standard_into_type(&rid, x_rowid) {}
into_type(rowid & rid, indicator & ind)
:standard_into_type(&rid, x_rowid, ind) {}
};
template <>
struct exchange_traits<soci::rowid>
{
typedef basic_type_tag type_family;
};
} // namespace details
} // namespace soci
#endif // SOCI_ROWID_EXCHANGE_H_INCLUDED

View File

@@ -0,0 +1,41 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_ROWID_H_INCLUDED
#define SOCI_ROWID_H_INCLUDED
#include "soci/soci-platform.h"
namespace soci
{
class session;
namespace details
{
class rowid_backend;
} // namespace details
// ROWID support
class SOCI_DECL rowid
{
public:
explicit rowid(session & s);
~rowid();
details::rowid_backend * get_backend() { return backEnd_; }
private:
details::rowid_backend *backEnd_;
};
} // namespace soci
#endif

View File

@@ -0,0 +1,224 @@
//
// Copyright (C) 2006-2008 Mateusz Loskot
// 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_ROWSET_H_INCLUDED
#define SOCI_ROWSET_H_INCLUDED
#include "soci/statement.h"
// std
#include <iterator>
#include <memory>
namespace soci
{
//
// rowset iterator of input category.
//
template <typename T>
class rowset_iterator
{
public:
// Standard iterator traits
typedef std::input_iterator_tag iterator_category;
typedef T value_type;
typedef T * pointer;
typedef T & reference;
typedef ptrdiff_t difference_type;
// Constructors
rowset_iterator()
: st_(0), define_(0)
{}
rowset_iterator(statement & st, T & define)
: st_(&st), define_(&define)
{
// Fetch first row to properly initialize iterator
++(*this);
}
// Access operators
reference operator*() const
{
return (*define_);
}
pointer operator->() const
{
return &(operator*());
}
// Iteration operators
rowset_iterator & operator++()
{
// Fetch next row from dataset
if (st_->fetch() == false)
{
// Set iterator to non-derefencable state (pass-the-end)
st_ = 0;
define_ = 0;
}
return (*this);
}
rowset_iterator operator++(int)
{
rowset_iterator tmp(*this);
++(*this);
return tmp;
}
// Comparison operators
bool operator==(rowset_iterator const & rhs) const
{
return (st_== rhs.st_ && define_ == rhs.define_);
}
bool operator!=(rowset_iterator const & rhs) const
{
return ((*this == rhs) == false);
}
private:
statement * st_;
T * define_;
}; // class rowset_iterator
namespace details
{
//
// Implementation of rowset
//
template <typename T>
class rowset_impl
{
public:
typedef rowset_iterator<T> iterator;
rowset_impl(details::prepare_temp_type const & prep)
: refs_(1), st_(new statement(prep)), define_(new T())
{
st_->exchange_for_rowset(into(*define_));
st_->execute();
}
void incRef()
{
++refs_;
}
void decRef()
{
if (--refs_ == 0)
{
delete this;
}
}
iterator begin() const
{
// No ownership transfer occurs here
return iterator(*st_, *define_);
}
iterator end() const
{
return iterator();
}
private:
unsigned int refs_;
#ifdef SOCI_CXX_C11
const std::unique_ptr<statement> st_;
const std::unique_ptr<T> define_;
#else
const std::auto_ptr<statement> st_;
const std::auto_ptr<T> define_;
#endif
SOCI_NOT_COPYABLE(rowset_impl)
}; // class rowset_impl
} // namespace details
//
// rowset is a thin wrapper on statement and provides access to STL-like input iterator.
// The rowset_iterator can be used to easily loop through statement results and
// use STL algorithms accepting input iterators.
//
template <typename T = soci::row>
class rowset
{
public:
typedef T value_type;
typedef rowset_iterator<T> iterator;
typedef rowset_iterator<T> const_iterator;
// this is a conversion constructor
rowset(details::prepare_temp_type const& prep)
: pimpl_(new details::rowset_impl<T>(prep))
{
}
rowset(rowset const & other)
: pimpl_(other.pimpl_)
{
pimpl_->incRef();
}
~rowset()
{
pimpl_->decRef();
}
rowset& operator=(rowset const& rhs)
{
if (&rhs != this)
{
rhs.pimpl_->incRef();
pimpl_->decRef();
pimpl_ = rhs.pimpl_;
}
return *this;
}
const_iterator begin() const
{
return pimpl_->begin();
}
const_iterator end() const
{
return pimpl_->end();
}
private:
// Pointer to implementation - the body
details::rowset_impl<T>* pimpl_;
}; // class rowset
} // namespace soci
#endif // SOCI_ROWSET_H_INCLUDED

View File

@@ -0,0 +1,158 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_SESSION_H_INCLUDED
#define SOCI_SESSION_H_INCLUDED
#include "soci/once-temp-type.h"
#include "soci/query_transformation.h"
#include "soci/connection-parameters.h"
// std
#include <cstddef>
#include <memory>
#include <ostream>
#include <sstream>
#include <string>
namespace soci
{
class values;
class backend_factory;
namespace details
{
class session_backend;
class statement_backend;
class rowid_backend;
class blob_backend;
} // namespace details
class connection_pool;
class SOCI_DECL session
{
private:
#ifdef SOCI_CXX_C11
void set_query_transformation_(std::unique_ptr<details::query_transformation_function> & qtf);
#else
void set_query_transformation_(std::auto_ptr<details::query_transformation_function> qtf);
#endif
public:
session();
explicit session(connection_parameters const & parameters);
session(backend_factory const & factory, std::string const & connectString);
session(std::string const & backendName, std::string const & connectString);
explicit session(std::string const & connectString);
explicit session(connection_pool & pool);
~session();
void open(connection_parameters const & parameters);
void open(backend_factory const & factory, std::string const & connectString);
void open(std::string const & backendName, std::string const & connectString);
void open(std::string const & connectString);
void close();
void reconnect();
void begin();
void commit();
void rollback();
// once and prepare are for syntax sugar only
details::once_type once;
details::prepare_type prepare;
// even more sugar
template <typename T>
details::once_temp_type operator<<(T const & t) { return once << t; }
std::ostringstream & get_query_stream();
std::string get_query() const;
template <typename T>
void set_query_transformation(T callback)
{
#ifdef SOCI_CXX_C11
std::unique_ptr<details::query_transformation_function> qtf(new details::query_transformation<T>(callback));
#else
std::auto_ptr<details::query_transformation_function> qtf(new details::query_transformation<T>(callback));
#endif
set_query_transformation_(qtf);
}
// support for basic logging
void set_log_stream(std::ostream * s);
std::ostream * get_log_stream() const;
void log_query(std::string const & query);
std::string get_last_query() const;
void set_got_data(bool gotData);
bool got_data() const;
void uppercase_column_names(bool forceToUpper);
bool get_uppercase_column_names() const;
// Functions for dealing with sequence/auto-increment values.
// If true is returned, value is filled with the next value from the given
// sequence. Otherwise either the sequence is invalid (doesn't exist) or
// the current backend doesn't support sequences. If you use sequences for
// automatically generating primary key values, you should use
// get_last_insert_id() after the insertion in this case.
bool get_next_sequence_value(std::string const & sequence, long & value);
// If true is returned, value is filled with the last auto-generated value
// for this table (although some backends ignore the table argument and
// return the last value auto-generated in this session).
bool get_last_insert_id(std::string const & table, long & value);
// for diagnostics and advanced users
// (downcast it to expected back-end session class)
details::session_backend * get_backend() { return backEnd_; }
std::string get_backend_name() const;
details::statement_backend * make_statement_backend();
details::rowid_backend * make_rowid_backend();
details::blob_backend * make_blob_backend();
private:
SOCI_NOT_COPYABLE(session)
std::ostringstream query_stream_;
details::query_transformation_function* query_transformation_;
std::ostream * logStream_;
std::string lastQuery_;
connection_parameters lastConnectParameters_;
bool uppercaseColumnNames_;
details::session_backend * backEnd_;
bool gotData_;
bool isFromPool_;
std::size_t poolPosition_;
connection_pool * pool_;
};
} // namespace soci
#endif // SOCI_SESSION_H_INCLUDED

View File

@@ -0,0 +1,265 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_BACKEND_H_INCLUDED
#define SOCI_BACKEND_H_INCLUDED
#include "soci/soci-platform.h"
#include "soci/error.h"
// std
#include <cstddef>
#include <map>
#include <string>
namespace soci
{
// data types, as seen by the user
enum data_type
{
dt_string, dt_date, dt_double, dt_integer, dt_long_long, dt_unsigned_long_long, dt_blob
};
// the enum type for indicator variables
enum indicator { i_ok, i_null, i_truncated };
class session;
namespace details
{
// data types, as used to describe exchange format
enum exchange_type
{
x_char,
x_stdstring,
x_short,
x_integer,
x_long_long,
x_unsigned_long_long,
x_double,
x_stdtm,
x_statement,
x_rowid,
x_blob
};
// type of statement (used for optimizing statement preparation)
enum statement_type
{
st_one_time_query,
st_repeatable_query
};
// polymorphic into type backend
class standard_into_type_backend
{
public:
standard_into_type_backend() {}
virtual ~standard_into_type_backend() {}
virtual void define_by_pos(int& position, void* data, exchange_type type) = 0;
virtual void pre_fetch() = 0;
virtual void post_fetch(bool gotData, bool calledFromFetch, indicator* ind) = 0;
virtual void clean_up() = 0;
private:
SOCI_NOT_COPYABLE(standard_into_type_backend)
};
class vector_into_type_backend
{
public:
vector_into_type_backend() {}
virtual ~vector_into_type_backend() {}
virtual void define_by_pos(int& position, void* data, exchange_type type) = 0;
virtual void pre_fetch() = 0;
virtual void post_fetch(bool gotData, indicator* ind) = 0;
virtual void resize(std::size_t sz) = 0;
virtual std::size_t size() = 0;
virtual void clean_up() = 0;
private:
SOCI_NOT_COPYABLE(vector_into_type_backend)
};
// polymorphic use type backend
class standard_use_type_backend
{
public:
standard_use_type_backend() {}
virtual ~standard_use_type_backend() {}
virtual void bind_by_pos(int& position, void* data,
exchange_type type, bool readOnly) = 0;
virtual void bind_by_name(std::string const& name,
void* data, exchange_type type, bool readOnly) = 0;
virtual void pre_use(indicator const* ind) = 0;
virtual void post_use(bool gotData, indicator * ind) = 0;
virtual void clean_up() = 0;
private:
SOCI_NOT_COPYABLE(standard_use_type_backend)
};
class vector_use_type_backend
{
public:
vector_use_type_backend() {}
virtual ~vector_use_type_backend() {}
virtual void bind_by_pos(int& position, void* data, exchange_type type) = 0;
virtual void bind_by_name(std::string const& name,
void* data, exchange_type type) = 0;
virtual void pre_use(indicator const* ind) = 0;
virtual std::size_t size() = 0;
virtual void clean_up() = 0;
private:
SOCI_NOT_COPYABLE(vector_use_type_backend)
};
// polymorphic statement backend
class statement_backend
{
public:
statement_backend() {}
virtual ~statement_backend() {}
virtual void alloc() = 0;
virtual void clean_up() = 0;
virtual void prepare(std::string const& query, statement_type eType) = 0;
enum exec_fetch_result
{
ef_success,
ef_no_data
};
virtual exec_fetch_result execute(int number) = 0;
virtual exec_fetch_result fetch(int number) = 0;
virtual long long get_affected_rows() = 0;
virtual int get_number_of_rows() = 0;
virtual std::string get_parameter_name(int index) const = 0;
virtual std::string rewrite_for_procedure_call(std::string const& query) = 0;
virtual int prepare_for_describe() = 0;
virtual void describe_column(int colNum, data_type& dtype,
std::string& column_name) = 0;
virtual standard_into_type_backend* make_into_type_backend() = 0;
virtual standard_use_type_backend* make_use_type_backend() = 0;
virtual vector_into_type_backend* make_vector_into_type_backend() = 0;
virtual vector_use_type_backend* make_vector_use_type_backend() = 0;
private:
SOCI_NOT_COPYABLE(statement_backend)
};
// polymorphic RowID backend
class rowid_backend
{
public:
virtual ~rowid_backend() {}
};
// polymorphic blob backend
class blob_backend
{
public:
blob_backend() {}
virtual ~blob_backend() {}
virtual std::size_t get_len() = 0;
virtual std::size_t read(std::size_t offset, char* buf,
std::size_t toRead) = 0;
virtual std::size_t write(std::size_t offset, char const* buf,
std::size_t toWrite) = 0;
virtual std::size_t append(char const* buf, std::size_t toWrite) = 0;
virtual void trim(std::size_t newLen) = 0;
private:
SOCI_NOT_COPYABLE(blob_backend)
};
// polymorphic session backend
class session_backend
{
public:
session_backend() {}
virtual ~session_backend() {}
virtual void begin() = 0;
virtual void commit() = 0;
virtual void rollback() = 0;
// At least one of these functions is usually not implemented for any given
// backend as RDBMS support either sequences or auto-generated values, so
// we don't declare them as pure virtuals to avoid having to define trivial
// versions of them in the derived classes. However every backend should
// define at least one of them to allow the code using auto-generated values
// to work.
virtual bool get_next_sequence_value(session&, std::string const&, long&)
{
return false;
}
virtual bool get_last_insert_id(session&, std::string const&, long&)
{
return false;
}
virtual std::string get_backend_name() const = 0;
virtual statement_backend* make_statement_backend() = 0;
virtual rowid_backend* make_rowid_backend() = 0;
virtual blob_backend* make_blob_backend() = 0;
private:
SOCI_NOT_COPYABLE(session_backend)
};
} // namespace details
// simple base class for the session back-end factory
class connection_parameters;
class SOCI_DECL backend_factory
{
public:
backend_factory() {}
virtual ~backend_factory() {}
virtual details::session_backend* make_session(
connection_parameters const& parameters) const = 0;
};
} // namespace soci
#endif // SOCI_BACKEND_H_INCLUDED

View File

@@ -0,0 +1,13 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCICONFIG_H_INCLUDED
#define SOCICONFIG_H_INCLUDED
#include "soci/soci-platform.h"
#endif // SOCICONFIG_H_INCLUDED

View File

@@ -0,0 +1,99 @@
//
// Copyright (C) 2006-2008 Mateusz Loskot
// 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_PLATFORM_H_INCLUDED
#define SOCI_PLATFORM_H_INCLUDED
//disable MSVC deprecated warnings
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdarg.h>
#include <string.h>
#include <string>
#include <cstring>
#include <cstdlib>
#include <ctime>
#if defined(_MSC_VER) || defined(__MINGW32__)
#define LL_FMT_FLAGS "I64"
#else
#define LL_FMT_FLAGS "ll"
#endif
// Portability hacks for Microsoft Visual C++ compiler
#ifdef _MSC_VER
#include <stdlib.h>
//Disables warnings about STL objects need to have dll-interface and/or
//base class must have dll interface
#pragma warning(disable:4251 4275)
// Define if you have the vsnprintf variants.
#if _MSC_VER < 1500
# define vsnprintf _vsnprintf
#endif
// Define if you have the snprintf variants.
#define snprintf _snprintf
// Define if you have the strtoll and strtoull variants.
#if _MSC_VER < 1300
# error "Visual C++ versions prior 1300 don't support _strtoi64 and _strtoui64"
#elif _MSC_VER >= 1300 && _MSC_VER < 1800
namespace std {
inline long long strtoll(char const* str, char** str_end, int base)
{
return _strtoi64(str, str_end, base);
}
inline unsigned long long strtoull(char const* str, char** str_end, int base)
{
return _strtoui64(str, str_end, base);
}
}
#endif // _MSC_VER < 1800
#endif // _MSC_VER
#if defined(__CYGWIN__) || defined(__MINGW32__)
#include <stdlib.h>
namespace std {
using ::strtoll;
using ::strtoull;
}
#endif
//define DLL import/export on WIN32
#ifdef _WIN32
# ifdef SOCI_DLL
# ifdef SOCI_SOURCE
# define SOCI_DECL __declspec(dllexport)
# else
# define SOCI_DECL __declspec(dllimport)
# endif // SOCI_SOURCE
# endif // SOCI_DLL
#endif // _WIN32
//
// If SOCI_DECL isn't defined yet define it now
#ifndef SOCI_DECL
# define SOCI_DECL
#endif
#define SOCI_NOT_ASSIGNABLE(classname) \
classname& operator=(const classname&);
#define SOCI_NOT_COPYABLE(classname) \
classname(const classname&); \
SOCI_NOT_ASSIGNABLE(classname)
#define SOCI_UNUSED(x) (void)x;
#endif // SOCI_PLATFORM_H_INCLUDED

View File

@@ -0,0 +1,159 @@
//
// Copyright (C) 2008 Maciej Sobczak
// 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_SIMPLE_H_INCLUDED
#define SOCI_SIMPLE_H_INCLUDED
#include "soci/soci-platform.h"
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
// session
typedef void * session_handle;
SOCI_DECL session_handle soci_create_session(char const * connectionString);
SOCI_DECL void soci_destroy_session(session_handle s);
SOCI_DECL void soci_begin(session_handle s);
SOCI_DECL void soci_commit(session_handle s);
SOCI_DECL void soci_rollback(session_handle s);
SOCI_DECL int soci_session_state(session_handle s);
SOCI_DECL char const * soci_session_error_message(session_handle s);
// blob
typedef void *blob_handle;
SOCI_DECL blob_handle soci_create_blob(session_handle s);
SOCI_DECL void soci_destroy_blob(blob_handle b);
SOCI_DECL int soci_blob_get_len(blob_handle b);
SOCI_DECL int soci_blob_read(blob_handle b, int offset, char *buf, int toRead);
SOCI_DECL int soci_blob_write(blob_handle b, int offset, char const *buf, int toWrite);
SOCI_DECL int soci_blob_append(blob_handle b, char const *buf, int toWrite);
SOCI_DECL int soci_blob_trim(blob_handle b, int newLen);
SOCI_DECL int soci_blob_state(blob_handle b);
SOCI_DECL char const * soci_blob_error_message(blob_handle b);
// statement
typedef void * statement_handle;
SOCI_DECL statement_handle soci_create_statement(session_handle s);
SOCI_DECL void soci_destroy_statement(statement_handle st);
// positional bind of into elments (the functions return the position for convenience)
SOCI_DECL int soci_into_string (statement_handle st);
SOCI_DECL int soci_into_int (statement_handle st);
SOCI_DECL int soci_into_long_long(statement_handle st);
SOCI_DECL int soci_into_double (statement_handle st);
SOCI_DECL int soci_into_date (statement_handle st);
SOCI_DECL int soci_into_blob (statement_handle st);
// vector versions
SOCI_DECL int soci_into_string_v (statement_handle st);
SOCI_DECL int soci_into_int_v (statement_handle st);
SOCI_DECL int soci_into_long_long_v(statement_handle st);
SOCI_DECL int soci_into_double_v (statement_handle st);
SOCI_DECL int soci_into_date_v (statement_handle st);
// positional read of into elements
SOCI_DECL int soci_get_into_state (statement_handle st, int position);
SOCI_DECL char const * soci_get_into_string (statement_handle st, int position);
SOCI_DECL int soci_get_into_int (statement_handle st, int position);
SOCI_DECL long long soci_get_into_long_long(statement_handle st, int position);
SOCI_DECL double soci_get_into_double (statement_handle st, int position);
SOCI_DECL char const * soci_get_into_date (statement_handle st, int position);
SOCI_DECL blob_handle soci_get_into_blob (statement_handle st, int position);
// positional (re)size of vectors
SOCI_DECL int soci_into_get_size_v(statement_handle st);
SOCI_DECL void soci_into_resize_v (statement_handle st, int new_size);
// positional read of vectors
SOCI_DECL int soci_get_into_state_v (statement_handle st, int position, int index);
SOCI_DECL char const * soci_get_into_string_v (statement_handle st, int position, int index);
SOCI_DECL int soci_get_into_int_v (statement_handle st, int position, int index);
SOCI_DECL long long soci_get_into_long_long_v(statement_handle st, int position, int index);
SOCI_DECL double soci_get_into_double_v (statement_handle st, int position, int index);
SOCI_DECL char const * soci_get_into_date_v (statement_handle st, int position, int index);
// named bind of use elements
SOCI_DECL void soci_use_string (statement_handle st, char const * name);
SOCI_DECL void soci_use_int (statement_handle st, char const * name);
SOCI_DECL void soci_use_long_long(statement_handle st, char const * name);
SOCI_DECL void soci_use_double (statement_handle st, char const * name);
SOCI_DECL void soci_use_date (statement_handle st, char const * name);
SOCI_DECL void soci_use_blob (statement_handle st, char const * name);
// vector versions
SOCI_DECL void soci_use_string_v (statement_handle st, char const * name);
SOCI_DECL void soci_use_int_v (statement_handle st, char const * name);
SOCI_DECL void soci_use_long_long_v(statement_handle st, char const * name);
SOCI_DECL void soci_use_double_v (statement_handle st, char const * name);
SOCI_DECL void soci_use_date_v (statement_handle st, char const * name);
// named write of use elements
SOCI_DECL void soci_set_use_state (statement_handle st, char const * name, int state);
SOCI_DECL void soci_set_use_string (statement_handle st, char const * name, char const * val);
SOCI_DECL void soci_set_use_int (statement_handle st, char const * name, int val);
SOCI_DECL void soci_set_use_long_long(statement_handle st, char const * name, long long val);
SOCI_DECL void soci_set_use_double (statement_handle st, char const * name, double val);
SOCI_DECL void soci_set_use_date (statement_handle st, char const * name, char const * val);
SOCI_DECL void soci_set_use_blob (statement_handle st, char const * name, blob_handle blob);
// positional (re)size of vectors
SOCI_DECL int soci_use_get_size_v(statement_handle st);
SOCI_DECL void soci_use_resize_v (statement_handle st, int new_size);
// named write of use vectors
SOCI_DECL void soci_set_use_state_v(statement_handle st,
char const * name, int index, int state);
SOCI_DECL void soci_set_use_string_v(statement_handle st,
char const * name, int index, char const * val);
SOCI_DECL void soci_set_use_int_v(statement_handle st,
char const * name, int index, int val);
SOCI_DECL void soci_set_use_long_long_v(statement_handle st,
char const * name, int index, long long val);
SOCI_DECL void soci_set_use_double_v(statement_handle st,
char const * name, int index, double val);
SOCI_DECL void soci_set_use_date_v(statement_handle st,
char const * name, int index, char const * val);
// named read of use elements (for modifiable use values)
SOCI_DECL int soci_get_use_state (statement_handle st, char const * name);
SOCI_DECL char const * soci_get_use_string (statement_handle st, char const * name);
SOCI_DECL int soci_get_use_int (statement_handle st, char const * name);
SOCI_DECL long long soci_get_use_long_long(statement_handle st, char const * name);
SOCI_DECL double soci_get_use_double (statement_handle st, char const * name);
SOCI_DECL char const * soci_get_use_date (statement_handle st, char const * name);
SOCI_DECL blob_handle soci_get_use_blob (statement_handle st, char const * name);
// statement preparation and execution
SOCI_DECL void soci_prepare(statement_handle st, char const * query);
SOCI_DECL int soci_execute(statement_handle st, int withDataExchange);
SOCI_DECL long long soci_get_affected_rows(statement_handle st);
SOCI_DECL int soci_fetch(statement_handle st);
SOCI_DECL int soci_got_data(statement_handle st);
SOCI_DECL int soci_statement_state(statement_handle s);
SOCI_DECL char const * soci_statement_error_message(statement_handle s);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // SOCI_SIMPLE_H_INCLUDED

View File

@@ -0,0 +1,56 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_H_INCLUDED
#define SOCI_H_INCLUDED
// namespace soci
#include "soci/soci-platform.h"
#include "soci/backend-loader.h"
#include "soci/blob.h"
#include "soci/blob-exchange.h"
#include "soci/connection-pool.h"
#include "soci/error.h"
#include "soci/exchange-traits.h"
#include "soci/into.h"
#include "soci/into-type.h"
#include "soci/once-temp-type.h"
#include "soci/prepare-temp-type.h"
#include "soci/procedure.h"
#include "soci/ref-counted-prepare-info.h"
#include "soci/ref-counted-statement.h"
#include "soci/row.h"
#include "soci/row-exchange.h"
#include "soci/rowid.h"
#include "soci/rowid-exchange.h"
#include "soci/rowset.h"
#include "soci/session.h"
#include "soci/soci-backend.h"
#include "soci/statement.h"
#include "soci/transaction.h"
#include "soci/type-conversion.h"
#include "soci/type-conversion-traits.h"
#include "soci/type-holder.h"
#include "soci/type-ptr.h"
#include "soci/unsigned-types.h"
#include "soci/use.h"
#include "soci/use-type.h"
#include "soci/values.h"
#include "soci/values-exchange.h"
// namespace boost
#ifdef SOCI_USE_BOOST
#include <boost/version.hpp>
#if defined(BOOST_VERSION) && BOOST_VERSION >= 103500
#include "soci/boost-fusion.h"
#endif // BOOST_VERSION
#include "soci/boost-optional.h"
#include "soci/boost-tuple.h"
#include "soci/boost-gregorian-date.h"
#endif // SOCI_USE_BOOST
#endif // SOCI_H_INCLUDED

View File

@@ -0,0 +1,317 @@
//
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney
// 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_SQLITE3_H_INCLUDED
#define SOCI_SQLITE3_H_INCLUDED
#ifdef _WIN32
# ifdef SOCI_DLL
# ifdef SOCI_SQLITE3_SOURCE
# define SOCI_SQLITE3_DECL __declspec(dllexport)
# else
# define SOCI_SQLITE3_DECL __declspec(dllimport)
# endif // SOCI_SQLITE3_SOURCE
# endif // SOCI_DLL
#endif // _WIN32
//
// If SOCI_SQLITE3_DECL isn't defined yet define it now
#ifndef SOCI_SQLITE3_DECL
# define SOCI_SQLITE3_DECL
#endif
#include <cstdarg>
#include <vector>
#include <soci/soci-backend.h>
// Disable flood of nonsense warnings generated for SQLite
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4510 4512 4610)
#endif
namespace sqlite_api
{
#if SQLITE_VERSION_NUMBER < 3003010
// The sqlite3_destructor_type typedef introduced in 3.3.10
// http://www.sqlite.org/cvstrac/tktview?tn=2191
typedef void (*sqlite3_destructor_type)(void*);
#endif
#include <sqlite3.h>
} // namespace sqlite_api
#undef SQLITE_STATIC
#define SQLITE_STATIC ((sqlite_api::sqlite3_destructor_type)0)
#ifdef _MSC_VER
#pragma warning(pop)
#endif
namespace soci
{
class sqlite3_soci_error : public soci_error
{
public:
sqlite3_soci_error(std::string const & msg, int result);
int result() const;
private:
int result_;
};
struct sqlite3_statement_backend;
struct sqlite3_standard_into_type_backend : details::standard_into_type_backend
{
sqlite3_standard_into_type_backend(sqlite3_statement_backend &st)
: statement_(st) {}
virtual void define_by_pos(int &position,
void *data, details::exchange_type type);
virtual void pre_fetch();
virtual void post_fetch(bool gotData, bool calledFromFetch,
indicator *ind);
virtual void clean_up();
sqlite3_statement_backend &statement_;
void *data_;
details::exchange_type type_;
int position_;
};
struct sqlite3_vector_into_type_backend : details::vector_into_type_backend
{
sqlite3_vector_into_type_backend(sqlite3_statement_backend &st)
: statement_(st) {}
void define_by_pos(int& position, void* data, details::exchange_type type);
void pre_fetch();
void post_fetch(bool gotData, indicator* ind);
void resize(std::size_t sz);
std::size_t size();
virtual void clean_up();
sqlite3_statement_backend& statement_;
void *data_;
details::exchange_type type_;
int position_;
};
struct sqlite3_standard_use_type_backend : details::standard_use_type_backend
{
sqlite3_standard_use_type_backend(sqlite3_statement_backend &st);
virtual void bind_by_pos(int &position,
void *data, details::exchange_type type, bool readOnly);
virtual void bind_by_name(std::string const &name,
void *data, details::exchange_type type, bool readOnly);
virtual void pre_use(indicator const *ind);
virtual void post_use(bool gotData, indicator *ind);
virtual void clean_up();
sqlite3_statement_backend &statement_;
void *data_; // pointer to used data: soci::use(myvariable) --> data_ = &myvariable
details::exchange_type type_; // type of data_
int position_; // binding position
std::string name_; // binding name
};
struct sqlite3_vector_use_type_backend : details::vector_use_type_backend
{
sqlite3_vector_use_type_backend(sqlite3_statement_backend &st)
: statement_(st) {}
virtual void bind_by_pos(int &position,
void *data, details::exchange_type type);
virtual void bind_by_name(std::string const &name,
void *data, details::exchange_type type);
virtual void pre_use(indicator const *ind);
virtual std::size_t size();
virtual void clean_up();
sqlite3_statement_backend &statement_;
void *data_;
details::exchange_type type_;
int position_;
std::string name_;
};
struct sqlite3_column
{
bool isNull_;
data_type type_;
union
{
struct
{
std::size_t size_;
union
{
const char *constData_;
char *data_;
};
} buffer_;
int int32_;
sqlite_api::sqlite3_int64 int64_;
double double_;
};
};
typedef std::vector<sqlite3_column> sqlite3_row;
typedef std::vector<sqlite3_row> sqlite3_recordset;
struct sqlite3_column_info
{
data_type type_;
std::string name_;
};
typedef std::vector<sqlite3_column_info> sqlite3_column_info_list;
struct sqlite3_session_backend;
struct sqlite3_statement_backend : details::statement_backend
{
sqlite3_statement_backend(sqlite3_session_backend &session);
virtual void alloc();
virtual void clean_up();
virtual void prepare(std::string const &query,
details::statement_type eType);
void reset_if_needed();
virtual exec_fetch_result execute(int number);
virtual exec_fetch_result fetch(int number);
virtual long long get_affected_rows();
virtual int get_number_of_rows();
virtual std::string get_parameter_name(int index) const;
virtual std::string rewrite_for_procedure_call(std::string const &query);
virtual int prepare_for_describe();
virtual void describe_column(int colNum, data_type &dtype,
std::string &columnName);
virtual sqlite3_standard_into_type_backend * make_into_type_backend();
virtual sqlite3_standard_use_type_backend * make_use_type_backend();
virtual sqlite3_vector_into_type_backend * make_vector_into_type_backend();
virtual sqlite3_vector_use_type_backend * make_vector_use_type_backend();
sqlite3_session_backend &session_;
sqlite_api::sqlite3_stmt *stmt_;
sqlite3_recordset dataCache_;
sqlite3_recordset useData_;
bool databaseReady_;
bool boundByName_;
bool boundByPos_;
sqlite3_column_info_list columns_;
long long rowsAffectedBulk_; // number of rows affected by the last bulk operation
private:
exec_fetch_result load_rowset(int totalRows);
exec_fetch_result load_one();
exec_fetch_result bind_and_execute(int number);
};
struct sqlite3_rowid_backend : details::rowid_backend
{
sqlite3_rowid_backend(sqlite3_session_backend &session);
~sqlite3_rowid_backend();
unsigned long value_;
};
struct sqlite3_blob_backend : details::blob_backend
{
sqlite3_blob_backend(sqlite3_session_backend &session);
~sqlite3_blob_backend();
virtual std::size_t get_len();
virtual std::size_t read(std::size_t offset, char *buf,
std::size_t toRead);
virtual std::size_t write(std::size_t offset, char const *buf,
std::size_t toWrite);
virtual std::size_t append(char const *buf, std::size_t toWrite);
virtual void trim(std::size_t newLen);
sqlite3_session_backend &session_;
std::size_t set_data(char const *buf, std::size_t toWrite);
const char *get_buffer() const { return buf_; }
private:
char *buf_;
size_t len_;
};
struct sqlite3_session_backend : details::session_backend
{
sqlite3_session_backend(connection_parameters const & parameters);
~sqlite3_session_backend();
virtual void begin();
virtual void commit();
virtual void rollback();
virtual bool get_last_insert_id(session&, std::string const&, long&);
virtual std::string get_backend_name() const { return "sqlite3"; }
void clean_up();
virtual sqlite3_statement_backend * make_statement_backend();
virtual sqlite3_rowid_backend * make_rowid_backend();
virtual sqlite3_blob_backend * make_blob_backend();
sqlite_api::sqlite3 *conn_;
};
struct sqlite3_backend_factory : backend_factory
{
sqlite3_backend_factory() {}
virtual sqlite3_session_backend * make_session(
connection_parameters const & parameters) const;
};
extern SOCI_SQLITE3_DECL sqlite3_backend_factory const sqlite3;
extern "C"
{
// for dynamic backend loading
SOCI_SQLITE3_DECL backend_factory const * factory_sqlite3();
SOCI_SQLITE3_DECL void register_factory_sqlite3();
} // extern "C"
} // namespace soci
#endif // SOCI_SQLITE3_H_INCLUDED

View File

@@ -0,0 +1,322 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_STATEMENT_H_INCLUDED
#define SOCI_STATEMENT_H_INCLUDED
#include "soci/bind-values.h"
#include "soci/into-type.h"
#include "soci/into.h"
#include "soci/noreturn.h"
#include "soci/use-type.h"
#include "soci/use.h"
#include "soci/soci-backend.h"
#include "soci/row.h"
// std
#include <cstddef>
#include <string>
#include <vector>
namespace soci
{
class session;
class values;
namespace details
{
class into_type_base;
class use_type_base;
class prepare_temp_type;
class SOCI_DECL statement_impl
{
public:
explicit statement_impl(session & s);
explicit statement_impl(prepare_temp_type const & prep);
~statement_impl();
void alloc();
void bind(values & v);
void exchange(into_type_ptr const & i) { intos_.exchange(i); }
template <typename T, typename Indicator>
void exchange(into_container<T, Indicator> const &ic)
{ intos_.exchange(ic); }
void exchange(use_type_ptr const & u) { uses_.exchange(u); }
template <typename T, typename Indicator>
void exchange(use_container<T, Indicator> const &uc)
{ uses_.exchange(uc); }
void clean_up();
void bind_clean_up();
void prepare(std::string const & query,
statement_type eType = st_repeatable_query);
void define_and_bind();
void undefine_and_bind();
bool execute(bool withDataExchange = false);
long long get_affected_rows();
bool fetch();
void describe();
void set_row(row * r);
void exchange_for_rowset(into_type_ptr const & i) { exchange_for_rowset_(i); }
template<typename T, typename Indicator>
void exchange_for_rowset(into_container<T, Indicator> const &ic)
{ exchange_for_rowset_(ic); }
// for diagnostics and advanced users
// (downcast it to expected back-end statement class)
statement_backend * get_backend() { return backEnd_; }
standard_into_type_backend * make_into_type_backend();
standard_use_type_backend * make_use_type_backend();
vector_into_type_backend * make_vector_into_type_backend();
vector_use_type_backend * make_vector_use_type_backend();
void inc_ref();
void dec_ref();
session & session_;
std::string rewrite_for_procedure_call(std::string const & query);
protected:
into_type_vector intos_;
use_type_vector uses_;
std::vector<indicator *> indicators_;
private:
// Call this method from a catch clause (only!) to rethrow the exception
// after adding the context in which it happened, including the provided
// description of the operation that failed, the SQL query and, if
// applicable, its parameters.
SOCI_NORETURN rethrow_current_exception_with_context(char const* operation);
int refCount_;
row * row_;
std::size_t fetchSize_;
std::size_t initialFetchSize_;
std::string query_;
into_type_vector intosForRow_;
int definePositionForRow_;
template <typename Into>
void exchange_for_rowset_(Into const &i)
{
if (intos_.empty() == false)
{
throw soci_error("Explicit into elements not allowed with rowset.");
}
intos_.exchange(i);
int definePosition = 1;
for(into_type_vector::iterator iter = intos_.begin(),
end = intos_.end();
iter != end; iter++)
{ (*iter)->define(*this, definePosition); }
definePositionForRow_ = definePosition;
}
template <typename T, typename Indicator>
void exchange_for_row(into_container<T, Indicator> const &ic)
{ intosForRow_.exchange(ic); }
void exchange_for_row(into_type_ptr const & i) { intosForRow_.exchange(i); }
void define_for_row();
template<typename T>
void into_row()
{
T * t = new T();
indicator * ind = new indicator(i_ok);
row_->add_holder(t, ind);
exchange_for_row(into(*t, *ind));
}
template<data_type>
void bind_into();
bool alreadyDescribed_;
std::size_t intos_size();
std::size_t uses_size();
void pre_fetch();
void pre_use();
void post_fetch(bool gotData, bool calledFromFetch);
void post_use(bool gotData);
bool resize_intos(std::size_t upperBound = 0);
void truncate_intos();
soci::details::statement_backend * backEnd_;
SOCI_NOT_COPYABLE(statement_impl)
};
} // namespace details
// Statement is a handle class for statement_impl
// (this provides copyability to otherwise non-copyable type)
class SOCI_DECL statement
{
public:
statement(session & s)
: impl_(new details::statement_impl(s)) {}
statement(details::prepare_temp_type const & prep)
: impl_(new details::statement_impl(prep)) {}
~statement() { impl_->dec_ref(); }
// copy is supported for this handle class
statement(statement const & other)
: impl_(other.impl_)
{
impl_->inc_ref();
}
void operator=(statement const & other)
{
other.impl_->inc_ref();
impl_->dec_ref();
impl_ = other.impl_;
}
void alloc() { impl_->alloc(); }
void bind(values & v) { impl_->bind(v); }
void exchange(details::into_type_ptr const & i) { impl_->exchange(i); }
template <typename T, typename Indicator>
void exchange(details::into_container<T, Indicator> const &ic) { impl_->exchange(ic); }
void exchange(details::use_type_ptr const & u) { impl_->exchange(u); }
template <typename T, typename Indicator>
void exchange(details::use_container<T, Indicator> const &uc) { impl_->exchange(uc); }
void clean_up() { impl_->clean_up(); }
void bind_clean_up() { impl_->bind_clean_up(); }
void prepare(std::string const & query,
details::statement_type eType = details::st_repeatable_query)
{
impl_->prepare(query, eType);
}
void define_and_bind() { impl_->define_and_bind(); }
void undefine_and_bind() { impl_->undefine_and_bind(); }
bool execute(bool withDataExchange = false)
{
gotData_ = impl_->execute(withDataExchange);
return gotData_;
}
long long get_affected_rows()
{
return impl_->get_affected_rows();
}
bool fetch()
{
gotData_ = impl_->fetch();
return gotData_;
}
bool got_data() const { return gotData_; }
void describe() { impl_->describe(); }
void set_row(row * r) { impl_->set_row(r); }
template <typename T, typename Indicator>
void exchange_for_rowset(details::into_container<T, Indicator> const & ic)
{
impl_->exchange_for_rowset(ic);
}
void exchange_for_rowset(details::into_type_ptr const & i)
{
impl_->exchange_for_rowset(i);
}
// for diagnostics and advanced users
// (downcast it to expected back-end statement class)
details::statement_backend * get_backend()
{
return impl_->get_backend();
}
details::standard_into_type_backend * make_into_type_backend()
{
return impl_->make_into_type_backend();
}
details::standard_use_type_backend * make_use_type_backend()
{
return impl_->make_use_type_backend();
}
details::vector_into_type_backend * make_vector_into_type_backend()
{
return impl_->make_vector_into_type_backend();
}
details::vector_use_type_backend * make_vector_use_type_backend()
{
return impl_->make_vector_use_type_backend();
}
std::string rewrite_for_procedure_call(std::string const & query)
{
return impl_->rewrite_for_procedure_call(query);
}
private:
details::statement_impl * impl_;
bool gotData_;
};
namespace details
{
// exchange_traits for statement
template <>
struct exchange_traits<statement>
{
typedef basic_type_tag type_family;
enum { x_type = x_statement };
};
// into and use types for Statement (for nested statements and cursors)
template <>
class into_type<statement> : public standard_into_type
{
public:
into_type(statement & s) : standard_into_type(&s, x_statement) {}
into_type(statement & s, indicator & ind)
: standard_into_type(&s, x_statement, ind) {}
};
template <>
class use_type<statement> : public standard_use_type
{
public:
use_type(statement & s, std::string const & name = std::string())
: standard_use_type(&s, x_statement, false, name) {}
use_type(statement & s, indicator & ind,
std::string const & name = std::string())
: standard_use_type(&s, x_statement, ind, false, name) {}
// Note: there is no const version of use for statement,
// because most likely it would not make much sense anyway.
};
} // namespace details
} // namespace soci
#endif // SOCI_STATEMENT_H_INCLUDED

View File

@@ -0,0 +1,36 @@
//
// Copyright (C) 2004-2008 Maciej Sobczak
// 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_TRANSACTION_H_INCLUDED
#define SOCI_TRANSACTION_H_INCLUDED
#include "soci/soci-platform.h"
#include "soci/session.h"
namespace soci
{
class SOCI_DECL transaction
{
public:
explicit transaction(session& sql);
~transaction();
void commit();
void rollback();
private:
bool handled_;
session& sql_;
SOCI_NOT_COPYABLE(transaction)
};
} // namespace soci
#endif // SOCI_TRANSACTION_H_INCLUDED

View File

@@ -0,0 +1,41 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_TYPE_CONVERSION_TRAITS_H_INCLUDED
#define SOCI_TYPE_CONVERSION_TRAITS_H_INCLUDED
#include "soci/soci-backend.h"
namespace soci
{
// default traits class type_conversion, acts as pass through for row::get()
// when no actual conversion is needed.
template <typename T, typename Enable = void>
struct type_conversion
{
typedef T base_type;
static void from_base(base_type const & in, indicator ind, T & out)
{
if (ind == i_null)
{
throw soci_error("Null value not allowed for this type");
}
out = in;
}
static void to_base(T const & in, base_type & out, indicator & ind)
{
out = in;
ind = i_ok;
}
};
} // namespace soci
#endif // SOCI_TYPE_CONVERSION_TRAITS_H_INCLUDED

View File

@@ -0,0 +1,364 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_TYPE_CONVERSION_H_INCLUDED
#define SOCI_TYPE_CONVERSION_H_INCLUDED
#include "soci/type-conversion-traits.h"
#include "soci/into-type.h"
#include "soci/use-type.h"
// std
#include <cstddef>
#include <string>
#include <vector>
namespace soci
{
namespace details
{
// this class is used to ensure correct order of construction
// of into_type and use_type elements that use type_conversion
template <typename T>
struct base_value_holder
{
typename type_conversion<T>::base_type val_;
};
// Automatically create into_type from a type_conversion
template <typename T>
class conversion_into_type
: private base_value_holder<T>,
public into_type<typename type_conversion<T>::base_type>
{
public:
typedef typename type_conversion<T>::base_type base_type;
conversion_into_type(T & value)
: into_type<base_type>(details::base_value_holder<T>::val_, ownInd_)
, value_(value)
, ownInd_()
, ind_(ownInd_)
{
}
conversion_into_type(T & value, indicator & ind)
: into_type<base_type>(details::base_value_holder<T>::val_, ind)
, value_(value)
, ownInd_(ind) // unused, just keep the pair of indicator(s) consistent
, ind_(ind)
{
}
private:
void convert_from_base()
{
type_conversion<T>::from_base(
details::base_value_holder<T>::val_, ind_, value_);
}
T & value_;
indicator ownInd_;
// ind_ refers to either ownInd_, or the one provided by the user
// in any case, ind_ refers to some valid indicator
// and can be used by conversion routines
indicator & ind_;
SOCI_NOT_COPYABLE(conversion_into_type)
};
// Automatically create use_type from a type_conversion
template <typename T>
class conversion_use_type
: private details::base_value_holder<T>,
public use_type<typename type_conversion<T>::base_type>
{
public:
typedef typename type_conversion<T>::base_type base_type;
conversion_use_type(T & value, std::string const & name = std::string())
: use_type<base_type>(details::base_value_holder<T>::val_, ownInd_, name)
, value_(value)
, ownInd_()
, ind_(ownInd_)
, readOnly_(false)
{
// TODO: likely to be removed (SHA: c166625a28f7c907318134f625ff5acea7d9a1f8)
//convert_to_base();
}
conversion_use_type(T const & value, std::string const & name = std::string())
: use_type<base_type>(details::base_value_holder<T>::val_, ownInd_, name)
, value_(const_cast<T &>(value))
, ownInd_()
, ind_(ownInd_)
, readOnly_(true)
{
// TODO: likely to be removed (SHA: c166625a28f7c907318134f625ff5acea7d9a1f8)
//convert_to_base();
}
conversion_use_type(T & value, indicator & ind,
std::string const & name = std::string())
: use_type<base_type>(details::base_value_holder<T>::val_, ind, name)
, value_(value)
, ind_(ind)
, readOnly_(false)
{
// TODO: likely to be removed (SHA: c166625a28f7c907318134f625ff5acea7d9a1f8)
//convert_to_base();
}
conversion_use_type(T const & value, indicator & ind,
std::string const & name = std::string())
: use_type<base_type>(details::base_value_holder<T>::val_, ind, name)
, value_(const_cast<T &>(value))
, ind_(ind)
, readOnly_(true)
{
// TODO: likely to be removed (SHA: c166625a28f7c907318134f625ff5acea7d9a1f8)
//convert_to_base();
}
void convert_from_base()
{
// NOTE:
// readOnly_ flag indicates that use_type object has been generated
// based on non-const object passed by user as input argument.
// For const objects, this is effectively no-op conversion.
// See standard_use_type::post_use() for more details.
if (readOnly_ == false)
{
type_conversion<T>::from_base(
details::base_value_holder<T>::val_, ind_, value_);
}
}
void convert_to_base()
{
type_conversion<T>::to_base(value_,
details::base_value_holder<T>::val_, ind_);
}
private:
T & value_;
indicator ownInd_;
// ind_ refers to either ownInd_, or the one provided by the user
// in any case, ind_ refers to some valid indicator
// and can be used by conversion routines
indicator & ind_;
bool readOnly_;
SOCI_NOT_COPYABLE(conversion_use_type)
};
// this class is used to ensure correct order of construction
// of vector based into_type and use_type elements that use type_conversion
template <typename T>
struct base_vector_holder
{
base_vector_holder(std::size_t sz = 0) : vec_(sz) {}
mutable std::vector<typename type_conversion<T>::base_type> vec_;
};
// Automatically create a std::vector based into_type from a type_conversion
template <typename T>
class conversion_into_type<std::vector<T> >
: private details::base_vector_holder<T>,
public into_type<std::vector<typename type_conversion<T>::base_type> >
{
public:
typedef typename std::vector
<
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::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)
{}
virtual std::size_t size() const
{
// the user might have resized his vector in the meantime
// -> synchronize the base-value mirror to have the same size
std::size_t const userSize = value_.size();
details::base_vector_holder<T>::vec_.resize(userSize);
return userSize;
}
virtual void resize(std::size_t sz)
{
value_.resize(sz);
ind_.resize(sz);
details::base_vector_holder<T>::vec_.resize(sz);
}
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)
{
type_conversion<T>::from_base(
details::base_vector_holder<T>::vec_[i], ind_[i], value_[i]);
}
}
std::vector<T> & value_;
std::vector<indicator> ownInd_;
// ind_ refers to either ownInd_, or the one provided by the user
// in any case, ind_ refers to some valid vector of indicators
// and can be used by conversion routines
std::vector<indicator> & ind_;
SOCI_NOT_COPYABLE(conversion_into_type)
};
// Automatically create a std::vector based use_type from a type_conversion
template <typename T>
class conversion_use_type<std::vector<T> >
: private details::base_vector_holder<T>,
public use_type<std::vector<typename type_conversion<T>::base_type> >
{
public:
typedef typename std::vector
<
typename type_conversion<T>::base_type
> 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_)
{
}
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)
{}
private:
void convert_from_base()
{
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)
{
type_conversion<T>::from_base(
details::base_vector_holder<T>::vec_[i], value_[i], ind_[i]);
}
}
void convert_to_base()
{
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)
{
type_conversion<T>::to_base(value_[i],
details::base_vector_holder<T>::vec_[i], ind_[i]);
}
}
std::vector<T> & value_;
std::vector<indicator> ownInd_;
// ind_ refers to either ownInd_, or the one provided by the user
// in any case, ind_ refers to some valid vector of indicators
// and can be used by conversion routines
std::vector<indicator> & ind_;
SOCI_NOT_COPYABLE(conversion_use_type)
};
template <typename T>
into_type_ptr do_into(T & t, user_type_tag)
{
return into_type_ptr(new conversion_into_type<T>(t));
}
template <typename T>
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>
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));
}
template <typename T>
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));
}
template <typename T>
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));
}
template <typename T>
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));
}
} // namespace details
} // namespace soci
#endif // SOCI_TYPE_CONVERSION_H_INCLUDED

View File

@@ -0,0 +1,68 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_TYPE_HOLDER_H_INCLUDED
#define SOCI_TYPE_HOLDER_H_INCLUDED
// std
#include <typeinfo>
namespace soci
{
namespace details
{
// Base class holder + derived class type_holder for storing type data
// instances in a container of holder objects
template <typename T>
class type_holder;
class holder
{
public:
holder() {}
virtual ~holder() {}
template<typename T>
T get()
{
type_holder<T>* p = dynamic_cast<type_holder<T> *>(this);
if (p)
{
return p->template value<T>();
}
else
{
throw std::bad_cast();
}
}
private:
template<typename T>
T value();
};
template <typename T>
class type_holder : public holder
{
public:
type_holder(T * t) : t_(t) {}
~type_holder() { delete t_; }
template<typename TypeValue>
TypeValue value() const { return *t_; }
private:
T * t_;
};
} // namespace details
} // namespace soci
#endif // SOCI_TYPE_HOLDER_H_INCLUDED

View File

@@ -0,0 +1,30 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_TYPE_PTR_H_INCLUDED
#define SOCI_TYPE_PTR_H_INCLUDED
namespace soci { namespace details {
template <typename T>
class type_ptr
{
public:
type_ptr(T * p) : p_(p) {}
~type_ptr() { delete p_; }
T * get() const { return p_; }
void release() const { p_ = 0; }
private:
mutable T * p_;
};
} // namespace details
} // namespace soci
#endif // SOCI_TYPE_PTR_H_INCLUDED

View File

@@ -0,0 +1,114 @@
//
// Copyright (C) 2010 Maciej Sobczak
// 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_UNSIGNED_TYPES_H_INCLUDED
#define SOCI_UNSIGNED_TYPES_H_INCLUDED
#include "soci/type-conversion-traits.h"
#include <limits>
namespace soci
{
// simple fall-back for unsigned types
template <>
struct type_conversion<unsigned char>
{
typedef long long base_type;
static void from_base(base_type const & in, indicator ind,
unsigned char & out)
{
if (ind == i_null)
{
throw soci_error("Null value not allowed for this type.");
}
const base_type max = (std::numeric_limits<unsigned char>::max)();
const base_type min = (std::numeric_limits<unsigned char>::min)();
if (in < min || in > max)
{
/* throw soci_error("Value outside of allowed range."); */
}
out = static_cast<unsigned char>(in);
}
static void to_base(unsigned char const & in,
base_type & out, indicator & ind)
{
out = static_cast<base_type>(in);
ind = i_ok;
}
};
template <>
struct type_conversion<unsigned short>
{
typedef long long base_type;
static void from_base(base_type const & in, indicator ind,
unsigned short & out)
{
if (ind == i_null)
{
throw soci_error("Null value not allowed for this type.");
}
const long long max = (std::numeric_limits<unsigned short>::max)();
const long long min = (std::numeric_limits<unsigned short>::min)();
if (in < min || in > max)
{
/* throw soci_error("Value outside of allowed range."); */
}
out = static_cast<unsigned short>(in);
}
static void to_base(unsigned short const & in,
base_type & out, indicator & ind)
{
out = static_cast<base_type>(in);
ind = i_ok;
}
};
template <>
struct type_conversion<unsigned int>
{
typedef long long base_type;
static void from_base(base_type const & in, indicator ind,
unsigned int & out)
{
if (ind == i_null)
{
throw soci_error("Null value not allowed for this type.");
}
const long long max = (std::numeric_limits<unsigned int>::max)();
const long long min = (std::numeric_limits<unsigned int>::min)();
if (in < min || in > max)
{
/* throw soci_error("Value outside of allowed range."); */
}
out = static_cast<unsigned int>(in);
}
static void to_base(unsigned int const & in,
base_type & out, indicator & ind)
{
out = static_cast<base_type>(in);
ind = i_ok;
}
};
} // namespace soci
#endif // SOCI_UNSIGNED_TYPES_H_INCLUDED

View File

@@ -0,0 +1,246 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_USE_TYPE_H_INCLUDED
#define SOCI_USE_TYPE_H_INCLUDED
#include "soci/soci-platform.h"
#include "soci/soci-backend.h"
#include "soci/type-ptr.h"
#include "soci/exchange-traits.h"
// std
#include <cstddef>
#include <ostream>
#include <string>
#include <vector>
namespace soci { namespace details {
class statement_impl;
// this is intended to be a base class for all classes that deal with
// binding input data (and OUT PL/SQL variables)
class SOCI_DECL use_type_base
{
public:
virtual ~use_type_base() {}
virtual void bind(statement_impl & st, int & position) = 0;
virtual std::string get_name() const = 0;
virtual void dump_value(std::ostream& os) const = 0;
virtual void pre_use() = 0;
virtual void post_use(bool gotData) = 0;
virtual void clean_up() = 0;
virtual std::size_t size() const = 0; // returns the number of elements
};
typedef type_ptr<use_type_base> use_type_ptr;
class SOCI_DECL standard_use_type : public use_type_base
{
public:
standard_use_type(void* data, exchange_type type,
bool readOnly, std::string const& name = std::string())
: data_(data)
, type_(type)
, ind_(NULL)
, readOnly_(readOnly)
, name_(name)
, backEnd_(NULL)
{
// FIXME: This was added with Ilia's patch
// https://github.com/SOCI/soci/commit/c166625a28f7c907318134f625ff5acea7d9a1f8
// but it seems to be a troublemaker, causing duplicated conversions
//convert_to_base();
}
standard_use_type(void* data, exchange_type type, indicator& ind,
bool readOnly, std::string const& name = std::string())
: data_(data)
, type_(type)
, ind_(&ind)
, readOnly_(readOnly)
, name_(name)
, backEnd_(NULL)
{
// FIXME
//convert_to_base();
}
virtual ~standard_use_type();
virtual void bind(statement_impl & st, int & position);
virtual std::string get_name() const { return name_; }
virtual void dump_value(std::ostream& os) const;
virtual void * get_data() { return data_; }
// conversion hook (from arbitrary user type to base type)
virtual void convert_to_base() {}
virtual void convert_from_base() {}
protected:
virtual void pre_use();
private:
virtual void post_use(bool gotData);
virtual void clean_up();
virtual std::size_t size() const { return 1; }
void* data_;
exchange_type type_;
indicator* ind_;
bool readOnly_;
std::string name_;
standard_use_type_backend* backEnd_;
};
class SOCI_DECL vector_use_type : public use_type_base
{
public:
vector_use_type(void* data, exchange_type type,
std::string const& name = std::string())
: data_(data)
, type_(type)
, ind_(NULL)
, 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)
, name_(name)
, backEnd_(NULL)
{}
~vector_use_type();
private:
virtual void bind(statement_impl& st, int & position);
virtual std::string get_name() const { return name_; }
virtual void dump_value(std::ostream& os) const;
virtual void pre_use();
virtual void post_use(bool) { /* nothing to do */ }
virtual void clean_up();
virtual std::size_t size() const;
void* data_;
exchange_type type_;
std::vector<indicator> const* ind_;
std::string name_;
vector_use_type_backend * backEnd_;
virtual void convert_to_base() {}
};
// implementation for the basic types (those which are supported by the library
// out of the box without user-provided conversions)
template <typename T>
class use_type : public standard_use_type
{
public:
use_type(T& t, std::string const& name = std::string())
: standard_use_type(&t,
static_cast<exchange_type>(exchange_traits<T>::x_type), false, name)
{}
use_type(T const& t, std::string const& name = std::string())
: standard_use_type(const_cast<T*>(&t),
static_cast<exchange_type>(exchange_traits<T>::x_type), true, name)
{}
use_type(T& t, indicator& ind, std::string const& name = std::string())
: standard_use_type(&t,
static_cast<exchange_type>(exchange_traits<T>::x_type), ind, false, name)
{}
use_type(T const& t, indicator& ind, std::string const& name = std::string())
: standard_use_type(const_cast<T*>(&t),
static_cast<exchange_type>(exchange_traits<T>::x_type), ind, false, name)
{}
};
template <typename T>
class use_type<std::vector<T> > : public vector_use_type
{
public:
use_type(std::vector<T>& v, std::string const& name = std::string())
: vector_use_type(&v,
static_cast<exchange_type>(exchange_traits<T>::x_type), 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>& 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)
{}
use_type(std::vector<T> const& v, std::vector<indicator> const& ind,
std::string const& name = std::string())
: vector_use_type(const_cast<std::vector<T> *>(&v),
static_cast<exchange_type>(exchange_traits<T>::x_type), ind, name)
{}
};
// helper dispatchers for basic types
template <typename T>
use_type_ptr do_use(T & t, std::string const & name, basic_type_tag)
{
return use_type_ptr(new use_type<T>(t, name));
}
template <typename T>
use_type_ptr do_use(T const & t, std::string const & name, basic_type_tag)
{
return use_type_ptr(new use_type<T>(t, name));
}
template <typename T>
use_type_ptr do_use(T & t, indicator & ind,
std::string const & name, basic_type_tag)
{
return use_type_ptr(new use_type<T>(t, ind, name));
}
template <typename T>
use_type_ptr do_use(T const & t, indicator & ind,
std::string const & name, basic_type_tag)
{
return use_type_ptr(new use_type<T>(t, ind, name));
}
template <typename T>
use_type_ptr do_use(T & t, std::vector<indicator> & ind,
std::string const & name, basic_type_tag)
{
return use_type_ptr(new use_type<T>(t, ind, name));
}
template <typename T>
use_type_ptr do_use(T const & t, std::vector<indicator> & ind,
std::string const & name, basic_type_tag)
{
return use_type_ptr(new use_type<T>(t, ind, name));
}
} // namespace details
} // namesapce soci
#endif // SOCI_USE_TYPE_H_INCLUDED

View File

@@ -0,0 +1,78 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_USE_H_INCLUDED
#define SOCI_USE_H_INCLUDED
#include "soci/use-type.h"
#include "soci/exchange-traits.h"
#include "soci/type-conversion.h"
#include "soci/soci-backend.h"
namespace soci
{
namespace details
{
template <typename T, typename Indicator>
struct use_container
{
use_container(T &_t, Indicator &_ind, const std::string &_name)
: t(_t), ind(_ind), name(_name) {}
T &t;
Indicator &ind;
const std::string &name;
private:
SOCI_NOT_ASSIGNABLE(use_container)
};
typedef void no_indicator;
template <typename T>
struct use_container<T, no_indicator>
{
use_container(T &_t, const std::string &_name)
: t(_t), name(_name) {}
T &t;
const std::string &name;
private:
SOCI_NOT_ASSIGNABLE(use_container)
};
} // namespace details
template <typename T>
details::use_container<T, details::no_indicator> use(T &t, const std::string &name = std::string())
{ return details::use_container<T, details::no_indicator>(t, name); }
template <typename T>
details::use_container<const T, details::no_indicator> use(T const &t, const std::string &name = std::string())
{ return details::use_container<const T, details::no_indicator>(t, name); }
template <typename T>
details::use_container<T, indicator> use(T &t, indicator & ind, std::string const &name = std::string())
{ return details::use_container<T, indicator>(t, ind, name); }
template <typename T>
details::use_container<const T, indicator> use(T const &t, indicator & ind, std::string const &name = std::string())
{ return details::use_container<const T, indicator>(t, ind, name); }
// vector containers
template <typename T>
details::use_container<T, std::vector<indicator> >
use(T &t, std::vector<indicator> & ind, const std::string &name = std::string())
{ return details::use_container<T, std::vector<indicator> >(t, ind, name); }
template <typename T>
details::use_container<std::vector<T>, details::no_indicator >
use(std::vector<T> &t, const std::string &name = std::string())
{ return details::use_container<std::vector<T>, details::no_indicator>(t, name); }
} // namespace soci
#endif // SOCI_USE_H_INCLUDED

View File

@@ -0,0 +1,148 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_VALUES_EXCHANGE_H_INCLUDED
#define SOCI_VALUES_EXCHANGE_H_INCLUDED
#include "soci/values.h"
#include "soci/into-type.h"
#include "soci/use-type.h"
#include "soci/row-exchange.h"
// std
#include <cstddef>
#include <sstream>
#include <string>
#include <vector>
namespace soci
{
namespace details
{
template <>
struct exchange_traits<values>
{
typedef basic_type_tag type_family;
// dummy value to satisfy the template engine, never used
enum { x_type = 0 };
};
template <>
class use_type<values> : public use_type_base
{
public:
use_type(values & v, std::string const & /*name*/ = std::string())
: v_(v)
{}
// we ignore the possibility to have the whole values as NULL
use_type(values & v, indicator /*ind*/, std::string const & /*name*/ = std::string())
: v_(v)
{}
virtual void bind(details::statement_impl & st, int & /*position*/)
{
v_.uppercase_column_names(st.session_.get_uppercase_column_names());
convert_to_base();
st.bind(v_);
}
virtual std::string get_name() const
{
std::ostringstream oss;
oss << "(";
std::size_t const num_columns = v_.get_number_of_columns();
for (std::size_t n = 0; n < num_columns; ++n)
{
if (n != 0)
oss << ", ";
oss << v_.get_properties(n).get_name();
}
oss << ")";
return oss.str();
}
virtual void dump_value(std::ostream& os) const
{
// TODO: Dump all columns.
os << "<value>";
}
virtual void post_use(bool /*gotData*/)
{
v_.reset_get_counter();
convert_from_base();
}
virtual void pre_use() {convert_to_base();}
virtual void clean_up() {v_.clean_up();}
virtual std::size_t size() const { return 1; }
// these are used only to re-dispatch to derived class
// (the derived class might be generated automatically by
// user conversions)
virtual void convert_to_base() {}
virtual void convert_from_base() {}
private:
values & v_;
SOCI_NOT_COPYABLE(use_type)
};
// this is not supposed to be used - no support for bulk ORM
template <>
class use_type<std::vector<values> >
{
private:
use_type();
};
template <>
class into_type<values> : public into_type<row>
{
public:
into_type(values & v)
: into_type<row>(v.get_row()), v_(v)
{}
into_type(values & v, indicator & ind)
: into_type<row>(v.get_row(), ind), v_(v)
{}
void clean_up()
{
v_.clean_up();
}
private:
values & v_;
SOCI_NOT_COPYABLE(into_type)
};
// this is not supposed to be used - no support for bulk ORM
template <>
class into_type<std::vector<values> >
{
private:
into_type();
};
} // namespace details
} // namespace soci
#endif // SOCI_VALUES_EXCHANGE_H_INCLUDED

View File

@@ -0,0 +1,354 @@
//
// Copyright (C) 2004-2008 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)
//
#ifndef SOCI_VALUES_H_INCLUDED
#define SOCI_VALUES_H_INCLUDED
#include "soci/statement.h"
#include "soci/into-type.h"
#include "soci/use-type.h"
// std
#include <cstddef>
#include <map>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
namespace soci
{
namespace details
{
class copy_base
{
public:
virtual ~copy_base() {}
};
template <typename T>
struct copy_holder : public copy_base
{
copy_holder(T const & v) : value_(v) {}
T value_;
};
} // namespace details
class SOCI_DECL values
{
friend class details::statement_impl;
friend class details::into_type<values>;
friend class details::use_type<values>;
public:
values() : row_(NULL), currentPos_(0), uppercaseColumnNames_(false) {}
indicator get_indicator(std::size_t pos) const;
indicator get_indicator(std::string const & name) const;
template <typename T>
T get(std::size_t pos) const
{
if (row_ != NULL)
{
return row_->get<T>(pos);
}
else if (*indicators_[pos] != i_null)
{
return get_from_uses<T>(pos);
}
else
{
std::ostringstream msg;
msg << "Column at position "
<< static_cast<unsigned long>(pos)
<< " contains NULL value and no default was provided";
throw soci_error(msg.str());
}
}
template <typename T>
T get(std::size_t pos, T const & nullValue) const
{
if (row_ != NULL)
{
return row_->get<T>(pos, nullValue);
}
else if (*indicators_[pos] == i_null)
{
return nullValue;
}
else
{
return get_from_uses<T>(pos);
}
}
template <typename T>
T get(std::string const & name) const
{
return row_ != NULL ? row_->get<T>(name) : get_from_uses<T>(name);
}
template <typename T>
T get(std::string const & name, T const & nullValue) const
{
return row_ != NULL
? row_->get<T>(name, nullValue)
: get_from_uses<T>(name, nullValue);
}
template <typename T>
values const & operator>>(T & value) const
{
if (row_ != NULL)
{
// row maintains its own position counter
// which is automatically reset when needed
*row_ >> value;
}
else if (*indicators_[currentPos_] != i_null)
{
// if there is no row object, then the data can be
// extracted from the locally stored use elements,
// but for this the position counter has to be maintained
// as well
value = get_from_uses<T>(currentPos_);
++currentPos_;
}
else
{
std::ostringstream msg;
msg << "Column at position "
<< static_cast<unsigned long>(currentPos_)
<< " contains NULL value and no default was provided";
throw soci_error(msg.str());
}
return *this;
}
void skip(std::size_t num = 1) const
{
if (row_ != NULL)
{
row_->skip(num);
}
else
{
currentPos_ += num;
}
}
void reset_get_counter() const
{
if (row_ != NULL)
{
row_->reset_get_counter();
}
else
{
currentPos_ = 0;
}
}
template <typename T>
void set(std::string const & name, T const & value, indicator indic = i_ok)
{
typedef typename type_conversion<T>::base_type base_type;
if(index_.find(name) == index_.end())
{
index_.insert(std::make_pair(name, uses_.size()));
indicator * pind = new indicator(indic);
indicators_.push_back(pind);
base_type baseValue;
if (indic == i_ok)
{
type_conversion<T>::to_base(value, baseValue, *pind);
}
details::copy_holder<base_type> * pcopy =
new details::copy_holder<base_type>(baseValue);
deepCopies_.push_back(pcopy);
uses_.push_back(new details::use_type<base_type>(
pcopy->value_, *pind, name));
}
else
{
size_t index = index_.find(name)->second;
*indicators_[index] = indic;
if (indic == i_ok)
{
type_conversion<T>::to_base(
value,
static_cast<details::copy_holder<base_type>*>(deepCopies_[index])->value_,
*indicators_[index]);
}
}
}
template <typename T>
void set(const T & value, indicator indic = i_ok)
{
indicator * pind = new indicator(indic);
indicators_.push_back(pind);
typedef typename type_conversion<T>::base_type base_type;
base_type baseValue;
type_conversion<T>::to_base(value, baseValue, *pind);
details::copy_holder<base_type> * pcopy =
new details::copy_holder<base_type>(baseValue);
deepCopies_.push_back(pcopy);
uses_.push_back(new details::use_type<base_type>(
pcopy->value_, *pind));
}
template <typename T>
values & operator<<(T const & value)
{
set(value);
return *this;
}
void uppercase_column_names(bool forceToUpper)
{
uppercaseColumnNames_ = forceToUpper;
}
std::size_t get_number_of_columns() const
{
return row_ ? row_->size() : 0;
}
column_properties const& get_properties(std::size_t pos) const;
column_properties const& get_properties(std::string const &name) const;
private:
//TODO To make values generally usable outside of type_conversion's,
// these should be reference counted smart pointers
row * row_;
std::vector<details::standard_use_type *> uses_;
std::map<details::use_type_base *, indicator *> unused_;
std::vector<indicator *> indicators_;
std::map<std::string, std::size_t> index_;
std::vector<details::copy_base *> deepCopies_;
mutable std::size_t currentPos_;
bool uppercaseColumnNames_;
// When type_conversion::to() is called, a values object is created
// without an underlying row object. In that case, get_from_uses()
// returns the underlying field values
template <typename T>
T get_from_uses(std::string const & name, T const & nullValue) const
{
std::map<std::string, std::size_t>::const_iterator pos = index_.find(name);
if (pos != index_.end())
{
if (*indicators_[pos->second] == i_null)
{
return nullValue;
}
return get_from_uses<T>(pos->second);
}
throw soci_error("Value named " + name + " not found.");
}
template <typename T>
T get_from_uses(std::string const & name) const
{
std::map<std::string, std::size_t>::const_iterator pos = index_.find(name);
if (pos != index_.end())
{
return get_from_uses<T>(pos->second);
}
throw soci_error("Value named " + name + " not found.");
}
template <typename T>
T get_from_uses(std::size_t pos) const
{
details::standard_use_type* u = uses_[pos];
typedef typename type_conversion<T>::base_type base_type;
if (dynamic_cast<details::use_type<base_type> *>(u))
{
base_type const & baseValue = *static_cast<base_type*>(u->get_data());
T val;
indicator ind = *indicators_[pos];
type_conversion<T>::from_base(baseValue, ind, val);
return val;
}
else
{
std::ostringstream msg;
msg << "Value at position "
<< static_cast<unsigned long>(pos)
<< " was set using a different type"
" than the one passed to get()";
throw soci_error(msg.str());
}
}
row& get_row()
{
row_ = new row();
row_->uppercase_column_names(uppercaseColumnNames_);
return * row_;
}
// this is called by Statement::bind(values)
void add_unused(details::use_type_base * u, indicator * i)
{
static_cast<details::standard_use_type *>(u)->convert_to_base();
unused_.insert(std::make_pair(u, i));
}
// this is called by details::into_type<values>::clean_up()
// and use_type<values>::clean_up()
void clean_up()
{
delete row_;
row_ = NULL;
// delete any uses and indicators which were created by set() but
// were not bound by the Statement
// (bound uses and indicators are deleted in Statement::clean_up())
for (std::map<details::use_type_base *, indicator *>::iterator pos =
unused_.begin(); pos != unused_.end(); ++pos)
{
delete pos->first;
delete pos->second;
}
for (std::size_t i = 0; i != deepCopies_.size(); ++i)
{
delete deepCopies_[i];
}
}
};
} // namespace soci
#endif // SOCI_VALUES_H_INCLUDED

View File

@@ -0,0 +1,34 @@
// SOCI version.hpp configuration header file
//
// Copyright (C) 2011 Mateusz Loskot <mateusz@loskot.net>
// 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_VERSION_HPP
#define SOCI_VERSION_HPP
// When updating the version here, don't forget to update it in CMakeLists.txt!
//
// Caution, this is the only SOCI header that is guarenteed
// to change with every SOCI release, including this header
// will cause a recompile every time a new SOCI version is
// released.
//
// SOCI_VERSION % 100 is the patch level
// SOCI_VERSION / 100 % 1000 is the minor version
// SOCI_VERSION / 100000 is the major version
#define SOCI_VERSION 400000
//
// SOCI_LIB_VERSION must be defined to be the same as SOCI_VERSION
// but as a *string* in the form "x_y[_z]" where x is the major version
// number, y is the minor version number, and z is the patch level if not 0.
#define SOCI_LIB_VERSION "4_0_0"
#endif // SOCI_VERSION_HPP