soci-backend.h   soci-backend.h 
// //
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton // Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
// Distributed under the Boost Software License, Version 1.0. // Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at // (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
// //
#ifndef SOCI_COMMON_H_INCLUDED #ifndef SOCI_BACKEND_H_INCLUDED
#define SOCI_COMMON_H_INCLUDED #define SOCI_BACKEND_H_INCLUDED
#include "soci-config.h"
#include "error.h"
// std
#include <cstddef> #include <cstddef>
#include <map> #include <map>
#include <stdexcept>
#include <string> #include <string>
#include "soci-config.h" namespace soci
namespace SOCI
{ {
// data types, as seen by the user // data types, as seen by the user
enum eDataType { eString, eChar, eDate, eDouble, eInteger, enum data_type
eUnsignedLong };
// the enum type for indicator variables
enum eIndicator { eOK, eNoData, eNull, eTruncated };
class SOCI_DECL SOCIError : public std::runtime_error
{ {
public: dt_string, dt_date, dt_double, dt_integer, dt_unsigned_long, dt_long_lo
SOCIError(std::string const & msg); ng, dt_unsigned_long_long
}; };
// the enum type for indicator variables
enum indicator { i_ok, i_null, i_truncated };
namespace details namespace details
{ {
// data types, as used to describe exchange format // data types, as used to describe exchange format
enum eExchangeType { eXChar, eXCString, eXStdString, eXShort, eXInteger, enum exchange_type
eXUnsignedLong, eXDouble, eXStdTm, eXStatement, {
eXRowID, eXBLOB }; x_char, x_stdstring,
x_short, x_integer,
x_unsigned_long, 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) // type of statement (used for optimizing statement preparation)
enum eStatementType { eOneTimeQuery, eRepeatableQuery }; enum statement_type
{
st_one_time_query,
st_repeatable_query
};
// polymorphic into type backend // polymorphic into type backend
class StandardIntoTypeBackEnd class standard_into_type_backend
{ {
public: public:
virtual ~StandardIntoTypeBackEnd() {} standard_into_type_backend() {}
virtual ~standard_into_type_backend() {}
virtual void defineByPos(int &position, virtual void define_by_pos(int& position, void* data, exchange_type typ
void *data, eExchangeType type) = 0; e) = 0;
virtual void preFetch() = 0; virtual void pre_fetch() = 0;
virtual void postFetch(bool gotData, bool calledFromFetch, virtual void post_fetch(bool gotData, bool calledFromFetch, indicator*
eIndicator *ind) = 0; ind) = 0;
virtual void cleanUp() = 0; virtual void clean_up() = 0;
private:
// noncopyable
standard_into_type_backend(standard_into_type_backend const&);
standard_into_type_backend& operator=(standard_into_type_backend const&
);
}; };
class VectorIntoTypeBackEnd class vector_into_type_backend
{ {
public: public:
virtual ~VectorIntoTypeBackEnd() {}
virtual void defineByPos(int &position, vector_into_type_backend() {}
void *data, eExchangeType type) = 0; virtual ~vector_into_type_backend() {}
virtual void define_by_pos(int& position, void* data, exchange_type typ
e) = 0;
virtual void preFetch() = 0; virtual void pre_fetch() = 0;
virtual void postFetch(bool gotData, eIndicator *ind) = 0; virtual void post_fetch(bool gotData, indicator* ind) = 0;
virtual void resize(std::size_t sz) = 0; virtual void resize(std::size_t sz) = 0;
virtual std::size_t size() = 0; virtual std::size_t size() = 0;
virtual void cleanUp() = 0; virtual void clean_up() = 0;
private:
// noncopyable
vector_into_type_backend(vector_into_type_backend const&);
vector_into_type_backend& operator=(vector_into_type_backend const&);
}; };
// polymorphic use type backend // polymorphic use type backend
class StandardUseTypeBackEnd class standard_use_type_backend
{ {
public: public:
virtual ~StandardUseTypeBackEnd() {} standard_use_type_backend() {}
virtual ~standard_use_type_backend() {}
virtual void bindByPos(int &position, virtual void bind_by_pos(int& position, void* data,
void *data, eExchangeType type) = 0; exchange_type type, bool readOnly) = 0;
virtual void bindByName(std::string const &name, virtual void bind_by_name(std::string const& name,
void *data, eExchangeType type) = 0; void* data, exchange_type type, bool readOnly) = 0;
virtual void preUse(eIndicator const *ind) = 0; virtual void pre_use(indicator const* ind) = 0;
virtual void postUse(bool gotData, eIndicator *ind) = 0; virtual void post_use(bool gotData, indicator * ind) = 0;
virtual void cleanUp() = 0; virtual void clean_up() = 0;
private:
// noncopyable
standard_use_type_backend(standard_use_type_backend const&);
standard_use_type_backend& operator=(standard_use_type_backend const&);
}; };
class VectorUseTypeBackEnd class vector_use_type_backend
{ {
public: public:
virtual ~VectorUseTypeBackEnd() {} vector_use_type_backend() {}
virtual ~vector_use_type_backend() {}
virtual void bindByPos(int &position, virtual void bind_by_pos(int& position, void* data, exchange_type type)
void *data, eExchangeType type) = 0; = 0;
virtual void bindByName(std::string const &name, virtual void bind_by_name(std::string const& name,
void *data, eExchangeType type) = 0; void* data, exchange_type type) = 0;
virtual void preUse(eIndicator const *ind) = 0; virtual void pre_use(indicator const* ind) = 0;
virtual std::size_t size() = 0; virtual std::size_t size() = 0;
virtual void cleanUp() = 0; virtual void clean_up() = 0;
private:
// noncopyable
vector_use_type_backend(vector_use_type_backend const&);
vector_use_type_backend& operator=(vector_use_type_backend const&);
}; };
// polymorphic statement backend // polymorphic statement backend
class StatementBackEnd class statement_backend
{ {
public: public:
virtual ~StatementBackEnd() {} statement_backend() {}
virtual ~statement_backend() {}
virtual void alloc() = 0; virtual void alloc() = 0;
virtual void cleanUp() = 0; virtual void clean_up() = 0;
virtual void prepare(std::string const& query, statement_type eType) =
0;
virtual void prepare(std::string const &query, eStatementType eType) = enum exec_fetch_result
0; {
ef_success,
ef_no_data
};
enum execFetchResult { eSuccess, eNoData }; virtual exec_fetch_result execute(int number) = 0;
virtual execFetchResult execute(int number) = 0; virtual exec_fetch_result fetch(int number) = 0;
virtual execFetchResult fetch(int number) = 0;
virtual int getNumberOfRows() = 0; virtual long long get_affected_rows() = 0;
virtual int get_number_of_rows() = 0;
virtual std::string rewriteForProcedureCall(std::string const &query) = 0; virtual std::string rewrite_for_procedure_call(std::string const& query ) = 0;
virtual int prepareForDescribe() = 0; virtual int prepare_for_describe() = 0;
virtual void describeColumn(int colNum, eDataType &dtype, virtual void describe_column(int colNum, data_type& dtype,
std::string &columnName) = 0; std::string& column_name) = 0;
virtual StandardIntoTypeBackEnd * makeIntoTypeBackEnd() = 0; virtual standard_into_type_backend* make_into_type_backend() = 0;
virtual StandardUseTypeBackEnd * makeUseTypeBackEnd() = 0; virtual standard_use_type_backend* make_use_type_backend() = 0;
virtual VectorIntoTypeBackEnd * makeVectorIntoTypeBackEnd() = 0; virtual vector_into_type_backend* make_vector_into_type_backend() = 0;
virtual VectorUseTypeBackEnd * makeVectorUseTypeBackEnd() = 0; virtual vector_use_type_backend* make_vector_use_type_backend() = 0;
private:
// noncopyable
statement_backend(statement_backend const&);
statement_backend& operator=(statement_backend const&);
}; };
// polymorphic RowID backend // polymorphic RowID backend
class RowIDBackEnd class rowid_backend
{ {
public: public:
virtual ~RowIDBackEnd() {} virtual ~rowid_backend() {}
}; };
// polymorphic RowID backend // polymorphic blob backend
class BLOBBackEnd class blob_backend
{ {
public: public:
virtual ~BLOBBackEnd() {} blob_backend() {}
virtual ~blob_backend() {}
virtual std::size_t getLen() = 0; virtual std::size_t get_len() = 0;
virtual std::size_t read(std::size_t offset, char *buf, virtual std::size_t read(std::size_t offset, char* buf,
std::size_t toRead) = 0; std::size_t toRead) = 0;
virtual std::size_t write(std::size_t offset, char const *buf, virtual std::size_t write(std::size_t offset, char const* buf,
std::size_t toWrite) = 0; std::size_t toWrite) = 0;
virtual std::size_t append(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; virtual void trim(std::size_t newLen) = 0;
private:
// noncopyable
blob_backend(blob_backend const&);
blob_backend& operator=(blob_backend const&);
}; };
// polymorphic session backend // polymorphic session backend
class SessionBackEnd class session_backend
{ {
public: public:
virtual ~SessionBackEnd() {} session_backend() {}
virtual ~session_backend() {}
virtual void begin() = 0; virtual void begin() = 0;
virtual void commit() = 0; virtual void commit() = 0;
virtual void rollback() = 0; virtual void rollback() = 0;
virtual StatementBackEnd * makeStatementBackEnd() = 0; virtual std::string get_backend_name() const = 0;
virtual RowIDBackEnd * makeRowIDBackEnd() = 0;
virtual BLOBBackEnd * makeBLOBBackEnd() = 0;
};
// helper class used to keep pointer and buffer size as a single object
struct CStringDescriptor
{
CStringDescriptor(char *str, std::size_t bufSize)
: str_(str), bufSize_(bufSize) {}
char *str_; virtual statement_backend* make_statement_backend() = 0;
std::size_t bufSize_; virtual rowid_backend* make_rowid_backend() = 0;
virtual blob_backend* make_blob_backend() = 0;
private:
// noncopyable
session_backend(session_backend const&);
session_backend& operator=(session_backend const&);
}; };
} // namespace details } // namespace details
// simple base class for the session back-end factory // simple base class for the session back-end factory
struct SOCI_DECL BackEndFactory struct SOCI_DECL backend_factory
{ {
virtual ~BackEndFactory() {} backend_factory() {}
virtual ~backend_factory() {}
virtual details::SessionBackEnd * makeSession( virtual details::session_backend* make_session(
std::string const &connectString) const = 0; std::string const& connectString) const = 0;
}; };
} // namespace SOCI } // namespace soci
#endif // SOCI_COMMON_H_INCLUDED #endif // SOCI_BACKEND_H_INCLUDED
 End of changes. 57 change blocks. 
97 lines changed or deleted 146 lines changed or added


 soci-config.h   soci-config.h 
// //
// Copyright (C) 2006 Mateusz Loskot // Copyright (C) 2006-2008 Mateusz Loskot
// Distributed under the Boost Software License, Version 1.0. // Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at // (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
// //
#ifndef SOCI_CONFIG_H_INCLUDED #ifndef SOCI_CONFIG_H_INCLUDED
#define SOCI_CONFIG_H_INCLUDED #define SOCI_CONFIG_H_INCLUDED
// //
// On Windows platform, define SOCI_DECL depending on // On Windows platform, define SOCI_DECL depending on
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 soci-empty.h   soci-empty.h 
skipping to change at line 28 skipping to change at line 28
# endif // SOCI_DLL # endif // SOCI_DLL
#endif // _WIN32 #endif // _WIN32
// //
// If SOCI_EMPTY_DECL isn't defined yet define it now // If SOCI_EMPTY_DECL isn't defined yet define it now
#ifndef SOCI_EMPTY_DECL #ifndef SOCI_EMPTY_DECL
# define SOCI_EMPTY_DECL # define SOCI_EMPTY_DECL
#endif #endif
#include "soci-backend.h" #include "soci-backend.h"
namespace SOCI #include <cstddef>
#include <string>
namespace soci
{ {
struct EmptyStatementBackEnd; struct empty_statement_backend;
struct SOCI_EMPTY_DECL EmptyStandardIntoTypeBackEnd : details::StandardInto
TypeBackEnd struct SOCI_EMPTY_DECL empty_standard_into_type_backend : details::standard
_into_type_backend
{ {
EmptyStandardIntoTypeBackEnd(EmptyStatementBackEnd &st) empty_standard_into_type_backend(empty_statement_backend &st)
: statement_(st) {} : statement_(st)
{}
virtual void defineByPos(int &position, void define_by_pos(int& position, void* data, details::exchange_type ty
void *data, details::eExchangeType type); pe);
virtual void preFetch(); void pre_fetch();
virtual void postFetch(bool gotData, bool calledFromFetch, void post_fetch(bool gotData, bool calledFromFetch, indicator* ind);
eIndicator *ind);
virtual void cleanUp(); void clean_up();
EmptyStatementBackEnd &statement_; empty_statement_backend& statement_;
}; };
struct SOCI_EMPTY_DECL EmptyVectorIntoTypeBackEnd : details::VectorIntoType BackEnd struct SOCI_EMPTY_DECL empty_vector_into_type_backend : details::vector_int o_type_backend
{ {
EmptyVectorIntoTypeBackEnd(EmptyStatementBackEnd &st) empty_vector_into_type_backend(empty_statement_backend &st)
: statement_(st) {} : statement_(st)
{}
virtual void defineByPos(int &position, void define_by_pos(int& position, void* data, details::exchange_type ty
void *data, details::eExchangeType type); pe);
virtual void preFetch(); void pre_fetch();
virtual void postFetch(bool gotData, eIndicator *ind); void post_fetch(bool gotData, indicator* ind);
virtual void resize(std::size_t sz); void resize(std::size_t sz);
virtual std::size_t size(); std::size_t size();
virtual void cleanUp(); void clean_up();
EmptyStatementBackEnd &statement_; empty_statement_backend& statement_;
}; };
struct SOCI_EMPTY_DECL EmptyStandardUseTypeBackEnd : details::StandardUseTy peBackEnd struct SOCI_EMPTY_DECL empty_standard_use_type_backend : details::standard_ use_type_backend
{ {
EmptyStandardUseTypeBackEnd(EmptyStatementBackEnd &st) empty_standard_use_type_backend(empty_statement_backend &st)
: statement_(st) {} : statement_(st)
{}
virtual void bindByPos(int &position, void bind_by_pos(int& position, void* data, details::exchange_type type
void *data, details::eExchangeType type); , bool readOnly);
virtual void bindByName(std::string const &name, void bind_by_name(std::string const& name, void* data, details::exchang
void *data, details::eExchangeType type); e_type type, bool readOnly);
virtual void preUse(eIndicator const *ind); void pre_use(indicator const* ind);
virtual void postUse(bool gotData, eIndicator *ind); void post_use(bool gotData, indicator* ind);
virtual void cleanUp(); void clean_up();
EmptyStatementBackEnd &statement_; empty_statement_backend& statement_;
}; };
struct SOCI_EMPTY_DECL EmptyVectorUseTypeBackEnd : details::VectorUseTypeBa ckEnd struct SOCI_EMPTY_DECL empty_vector_use_type_backend : details::vector_use_ type_backend
{ {
EmptyVectorUseTypeBackEnd(EmptyStatementBackEnd &st) empty_vector_use_type_backend(empty_statement_backend &st)
: statement_(st) {} : statement_(st) {}
virtual void bindByPos(int &position, void bind_by_pos(int& position, void* data, details::exchange_type type
void *data, details::eExchangeType type); );
virtual void bindByName(std::string const &name, void bind_by_name(std::string const& name, void* data, details::exchang
void *data, details::eExchangeType type); e_type type);
virtual void preUse(eIndicator const *ind); void pre_use(indicator const* ind);
virtual std::size_t size(); std::size_t size();
virtual void cleanUp(); void clean_up();
EmptyStatementBackEnd &statement_; empty_statement_backend& statement_;
}; };
struct EmptySessionBackEnd; struct empty_session_backend;
struct SOCI_EMPTY_DECL EmptyStatementBackEnd : details::StatementBackEnd struct SOCI_EMPTY_DECL empty_statement_backend : details::statement_backend
{ {
EmptyStatementBackEnd(EmptySessionBackEnd &session); empty_statement_backend(empty_session_backend &session);
virtual void alloc(); void alloc();
virtual void cleanUp(); void clean_up();
virtual void prepare(std::string const &query, void prepare(std::string const& query, details::statement_type eType);
details::eStatementType eType);
virtual execFetchResult execute(int number); exec_fetch_result execute(int number);
virtual execFetchResult fetch(int number); exec_fetch_result fetch(int number);
virtual int getNumberOfRows(); long long get_affected_rows();
int get_number_of_rows();
virtual std::string rewriteForProcedureCall(std::string const &query); std::string rewrite_for_procedure_call(std::string const& query);
virtual int prepareForDescribe(); int prepare_for_describe();
virtual void describeColumn(int colNum, eDataType &dtype, void describe_column(int colNum, data_type& dtype, std::string& columnN
std::string &columnName); ame);
virtual EmptyStandardIntoTypeBackEnd * makeIntoTypeBackEnd(); empty_standard_into_type_backend* make_into_type_backend();
virtual EmptyStandardUseTypeBackEnd * makeUseTypeBackEnd(); empty_standard_use_type_backend* make_use_type_backend();
virtual EmptyVectorIntoTypeBackEnd * makeVectorIntoTypeBackEnd(); empty_vector_into_type_backend* make_vector_into_type_backend();
virtual EmptyVectorUseTypeBackEnd * makeVectorUseTypeBackEnd(); empty_vector_use_type_backend* make_vector_use_type_backend();
EmptySessionBackEnd &session_; empty_session_backend& session_;
}; };
struct EmptyRowIDBackEnd : details::RowIDBackEnd struct empty_rowid_backend : details::rowid_backend
{ {
EmptyRowIDBackEnd(EmptySessionBackEnd &session); empty_rowid_backend(empty_session_backend &session);
~EmptyRowIDBackEnd(); ~empty_rowid_backend();
}; };
struct EmptyBLOBBackEnd : details::BLOBBackEnd struct empty_blob_backend : details::blob_backend
{ {
EmptyBLOBBackEnd(EmptySessionBackEnd &session); empty_blob_backend(empty_session_backend& session);
~EmptyBLOBBackEnd(); ~empty_blob_backend();
virtual std::size_t getLen(); std::size_t get_len();
virtual std::size_t read(std::size_t offset, char *buf, std::size_t read(std::size_t offset, char* buf, std::size_t toRead);
std::size_t toRead); std::size_t write(std::size_t offset, char const* buf, std::size_t toWr
virtual std::size_t write(std::size_t offset, char const *buf, ite);
std::size_t toWrite); std::size_t append(char const* buf, std::size_t toWrite);
virtual std::size_t append(char const *buf, std::size_t toWrite); void trim(std::size_t newLen);
virtual void trim(std::size_t newLen);
EmptySessionBackEnd &session_; empty_session_backend& session_;
}; };
struct EmptySessionBackEnd : details::SessionBackEnd struct empty_session_backend : details::session_backend
{ {
EmptySessionBackEnd(std::string const &connectString); empty_session_backend(std::string const& connectString);
~EmptySessionBackEnd(); ~empty_session_backend();
virtual void begin(); void begin();
virtual void commit(); void commit();
virtual void rollback(); void rollback();
void cleanUp(); std::string get_backend_name() const { return "empty"; }
virtual EmptyStatementBackEnd * makeStatementBackEnd(); void clean_up();
virtual EmptyRowIDBackEnd * makeRowIDBackEnd();
virtual EmptyBLOBBackEnd * makeBLOBBackEnd(); empty_statement_backend* make_statement_backend();
empty_rowid_backend* make_rowid_backend();
empty_blob_backend* make_blob_backend();
}; };
struct SOCI_EMPTY_DECL EmptyBackEndFactory : BackEndFactory struct SOCI_EMPTY_DECL empty_backend_factory : backend_factory
{ {
virtual EmptySessionBackEnd * makeSession( empty_backend_factory() {}
std::string const &connectString) const; empty_session_backend* make_session(std::string const& connectString) c
onst;
}; };
SOCI_EMPTY_DECL extern EmptyBackEndFactory const empty; 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 } // namespace soci
#endif // SOCI_EMPTY_H_INCLUDED #endif // SOCI_EMPTY_H_INCLUDED
 End of changes. 54 change blocks. 
93 lines changed or deleted 110 lines changed or added


 soci-platform.h   soci-platform.h 
// //
// Copyright (C) 2006 Mateusz Loskot // Copyright (C) 2006-2008 Mateusz Loskot
// Distributed under the Boost Software License, Version 1.0. // Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at // (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
// //
#ifndef SOCI_PLATFORM_H_INCLUDED #ifndef SOCI_PLATFORM_H_INCLUDED
#define SOCI_PLATFORM_H_INCLUDED #define SOCI_PLATFORM_H_INCLUDED
// Portability hacks for Microsoft Visual C++ compiler // Portability hacks for Microsoft Visual C++ compiler
#ifdef _MSC_VER #ifdef _MSC_VER
// Define if you have the vsnprintf variants. // Define if you have the vsnprintf variants.
#define HAVE_VSNPRINTF 1 #if _MSC_VER < 1500
#define vsnprintf _vsnprintf # define HAVE_VSNPRINTF 1
# define vsnprintf _vsnprintf
#endif
// Define if you have the snprintf variants. // Define if you have the snprintf variants.
#define HAVE_SNPRINTF 1 #define HAVE_SNPRINTF 1
#define snprintf _snprintf #define snprintf _snprintf
// Define if you have the strtoll variants. // Define if you have the strtoll variants.
#if _MSC_VER >= 1300 #if _MSC_VER >= 1300
# define HAVE_STRTOLL 1 # define HAVE_STRTOLL 1
# define strtoll(nptr, endptr, base) _strtoi64(nptr, endptr, base) # define strtoll(nptr, endptr, base) _strtoi64(nptr, endptr, base)
#else #else
# // XXX - Visual C++ versions prior 1300 don't support strtoi64
# undef HAVE_STRTOLL # undef HAVE_STRTOLL
# error "Visual C++ versions prior 1300 don't support strtoi64"
#endif // _MSC_VER >= 1300 #endif // _MSC_VER >= 1300
#endif // _MSC_VER #endif // _MSC_VER
#endif // SOCI_PLATFORM_H_INCLUDED #endif // SOCI_PLATFORM_H_INCLUDED
 End of changes. 5 change blocks. 
4 lines changed or deleted 7 lines changed or added


 soci.h   soci.h 
// //
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton // Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
// Distributed under the Boost Software License, Version 1.0. // Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at // (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
// //
#ifndef SOCI_H_INCLUDED #ifndef SOCI_H_INCLUDED
#define SOCI_H_INCLUDED #define SOCI_H_INCLUDED
#include <map>
#include <string>
#include <vector>
#include <ostream>
#include <sstream>
#include <ctime>
#include <cassert>
#include "soci-config.h"
#include "soci-backend.h"
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(disable:4251 4512 4511) #pragma warning(disable:4251 4512 4511)
#endif #endif
namespace SOCI // namespace soci
{ #include "backend-loader.h"
#include "blob.h"
class Session; #include "blob-exchange.h"
class Statement; #include "connection-pool.h"
#include "error.h"
// default traits class TypeConversion, acts as pass through for Row::get() #include "exchange-traits.h"
// when no actual conversion is needed. #include "into.h"
template<typename T> #include "into-type.h"
struct TypeConversion #include "once-temp-type.h"
{ #include "prepare-temp-type.h"
typedef T base_type; #include "procedure.h"
static T from(T const &t) { return t; } #include "ref-counted-prepare-info.h"
}; #include "ref-counted-statement.h"
#include "row.h"
// TypeConversion specializations must use a stock type as the base_type. #include "row-exchange.h"
// Each such specialization automatically creates a UseType and an IntoType #include "rowid.h"
. #include "rowid-exchange.h"
// This code is commented out, since it causes problems in those environmen #include "rowset.h"
ts #include "session.h"
// where std::time_t is an alias to int. #include "soci-backend.h"
// #include "soci-config.h"
// template<> #include "soci-platform.h"
// struct TypeConversion<std::time_t> #include "statement.h"
// {: #include "transaction.h"
// typedef std::tm base_type; #include "type-conversion.h"
// static std::time_t from(std::tm& t) { return mktime(&t); } #include "type-conversion-traits.h"
// static std::tm to(std::time_t& t) { return *localtime(&t); } #include "type-holder.h"
// }; #include "type-ptr.h"
#include "unsigned-types.h"
namespace details #include "use.h"
{ #include "use-type.h"
#include "values.h"
class StatementImpl; #include "values-exchange.h"
// this is intended to be a base class for all classes that deal with // namespace boost
// defining output data #ifdef SOCI_USE_BOOST
class IntoTypeBase #include <boost/version.hpp>
{ #if defined(BOOST_VERSION) && BOOST_VERSION >= 103500
public: #include "boost-fusion.h"
virtual ~IntoTypeBase() {} #endif // BOOST_VERSION
#include "boost-optional.h"
virtual void define(details::StatementImpl &st, int &position) = 0; #include "boost-tuple.h"
virtual void preFetch() = 0; #include "boost-gregorian-date.h"
virtual void postFetch(bool gotData, bool calledFromFetch) = 0; #endif // SOCI_USE_BOOST
virtual void cleanUp() = 0;
virtual std::size_t size() const = 0; // returns the number of element
s
virtual void resize(std::size_t /* sz */) {} // used for vectors only
};
// 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 UseTypeBase
{
public:
virtual ~UseTypeBase() {}
virtual void bind(details::StatementImpl &st, int &position) = 0;
virtual void preUse() = 0;
virtual void postUse(bool gotData) = 0;
virtual void cleanUp() = 0;
virtual std::size_t size() const = 0; // returns the number of element
s
};
template <typename T>
class TypePtr
{
public:
TypePtr(T *p) : p_(p) {}
~TypePtr() { delete p_; }
T * get() const { return p_; }
void release() const { p_ = NULL; }
private:
mutable T *p_;
};
typedef TypePtr<IntoTypeBase> IntoTypePtr;
typedef TypePtr<UseTypeBase> UseTypePtr;
// general case not implemented
template <typename T>
class IntoType;
// general case not implemented
template <typename T>
class UseType;
} // namespace details
// the into function is a helper for defining output variables
template <typename T>
details::IntoTypePtr into(T &t)
{
return details::IntoTypePtr(new details::IntoType<T>(t));
}
template <typename T, typename T1>
details::IntoTypePtr into(T &t, T1 p1)
{
return details::IntoTypePtr(new details::IntoType<T>(t, p1));
}
template <typename T>
details::IntoTypePtr into(T &t, std::vector<eIndicator> &indicator)
{
return details::IntoTypePtr(new details::IntoType<T>(t, indicator));
}
template <typename T>
details::IntoTypePtr into(T &t, eIndicator &indicator)
{
return details::IntoTypePtr(new details::IntoType<T>(t, indicator));
}
template <typename T, typename T1, typename T2>
details::IntoTypePtr into(T &t, T1 p1, T2 p2)
{
return details::IntoTypePtr(new details::IntoType<T>(t, p1, p2));
}
template <typename T, typename T1>
details::IntoTypePtr into(T &t, eIndicator &ind, T1 p1)
{
return details::IntoTypePtr(new details::IntoType<T>(t, ind, p1));
}
template <typename T, typename T1, typename T2, typename T3>
details::IntoTypePtr into(T &t, T1 p1, T2 p2, T3 p3)
{
return details::IntoTypePtr(new details::IntoType<T>(t, p1, p2, p3));
}
template <typename T, typename T1, typename T2>
details::IntoTypePtr into(T &t, eIndicator &ind, T1 p1, T2 p2)
{
return details::IntoTypePtr(new details::IntoType<T>(t, ind, p1, p2));
}
template <typename T, typename T1, typename T2, typename T3, typename T4>
details::IntoTypePtr into(T &t, T1 p1, T2 p2, T3 p3, T4 p4)
{
return details::IntoTypePtr(new details::IntoType<T>(t, p1, p2, p3, p4)
);
}
template <typename T, typename T1, typename T2, typename T3>
details::IntoTypePtr into(T &t, eIndicator &ind, T1 p1, T2 p2, T3 p3)
{
return details::IntoTypePtr(new details::IntoType<T>(t, ind, p1, p2, p3
));
}
template <typename T, typename T1, typename T2, typename T3,
typename T4, typename T5>
details::IntoTypePtr into(T &t, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5)
{
return details::IntoTypePtr(
new details::IntoType<T>(t, p1, p2, p3, p4, p5));
}
template <typename T, typename T1, typename T2, typename T3, typename T4>
details::IntoTypePtr into(T &t, eIndicator &ind, T1 p1, T2 p2, T3 p3, T4 p4
)
{
return details::IntoTypePtr(
new details::IntoType<T>(t, ind, p1, p2, p3, p4));
}
// the use function is a helper for binding input variables
// (and output PL/SQL parameters)
template <typename T>
details::UseTypePtr use(T &t)
{
return details::UseTypePtr(new details::UseType<T>(t));
}
template <typename T, typename T1>
details::UseTypePtr use(T &t, T1 p1)
{
return details::UseTypePtr(new details::UseType<T>(t, p1));
}
template <typename T>
details::UseTypePtr use(T &t, std::vector<eIndicator> const &indicator)
{
return details::UseTypePtr(new details::UseType<T>(t, indicator));
}
template <typename T>
details::UseTypePtr use(T &t, eIndicator &indicator)
{
return details::UseTypePtr(new details::UseType<T>(t, indicator));
}
template <typename T, typename T1, typename T2>
details::UseTypePtr use(T &t, T1 p1, T2 p2)
{
return details::UseTypePtr(new details::UseType<T>(t, p1, p2));
}
template <typename T, typename T1>
details::UseTypePtr use(T &t, eIndicator &ind, T1 p1)
{
return details::UseTypePtr(new details::UseType<T>(t, ind, p1));
}
template <typename T, typename T1>
details::UseTypePtr use(T &t, std::vector<eIndicator> const &ind, T1 p1)
{
return details::UseTypePtr(new details::UseType<T>(t, ind, p1));
}
template <typename T, typename T1, typename T2, typename T3>
details::UseTypePtr use(T &t, T1 p1, T2 p2, T3 p3)
{
return details::UseTypePtr(new details::UseType<T>(t, p1, p2, p3));
}
template <typename T, typename T1, typename T2>
details::UseTypePtr use(T &t, eIndicator &ind, T1 p1, T2 p2)
{
return details::UseTypePtr(new details::UseType<T>(t, ind, p1, p2));
}
template <typename T, typename T1, typename T2, typename T3, typename T4>
details::UseTypePtr use(T &t, T1 p1, T2 p2, T3 p3, T4 p4)
{
return details::UseTypePtr(new details::UseType<T>(t, p1, p2, p3, p4));
}
template <typename T, typename T1, typename T2, typename T3>
details::UseTypePtr use(T &t, eIndicator &ind, T1 p1, T2 p2, T3 p3)
{
return details::UseTypePtr(new details::UseType<T>(t, ind, p1, p2, p3))
;
}
template <typename T, typename T1, typename T2, typename T3,
typename T4, typename T5>
details::UseTypePtr use(T &t, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5)
{
return details::UseTypePtr(
new details::UseType<T>(t, p1, p2, p3, p4, p5));
}
template <typename T, typename T1, typename T2, typename T3, typename T4>
details::UseTypePtr use(T &t, eIndicator &ind, T1 p1, T2 p2, T3 p3, T4 p4)
{
return details::UseTypePtr(
new details::UseType<T>(t, ind, p1, p2, p3, p4));
}
namespace details
{
class PrepareTempType;
// Base class Holder + derived class TypeHolder for storing type data
// instances in a container of Holder objects
template <typename T>
class TypeHolder;
class Holder
{
public:
Holder(){}
virtual ~Holder(){};
template<typename T>
T get()
{
TypeHolder<T>* p = dynamic_cast<TypeHolder<T> *>(this);
if (p)
{
return p->value<T>();
}
else
{
throw std::bad_cast();
}
}
private:
template<typename T> T value();
};
template <typename T>
class TypeHolder : public Holder
{
public:
TypeHolder(T* t) : t_(t) {}
~TypeHolder() { delete t_; }
template<typename TVAL> TVAL value() const { return *t_; }
private:
T* t_;
};
} // namespace details
class SOCI_DECL ColumnProperties
{
// use getters/setters in case we want to make some
// of the getters lazy in the future
public:
std::string getName() const { return name_; }
eDataType getDataType() const { return dataType_; }
void setName(std::string const &name) { name_ = name; }
void setDataType(eDataType dataType) { dataType_ = dataType; }
private:
std::string name_;
eDataType dataType_;
};
class SOCI_DECL Row
{
public:
void addProperties(ColumnProperties const &cp);
std::size_t size() const;
eIndicator indicator(std::size_t pos) const;
eIndicator indicator(std::string const &name) const;
template <typename T>
inline void addHolder(T* t, eIndicator* ind)
{
holders_.push_back(new details::TypeHolder<T>(t));
indicators_.push_back(ind);
}
ColumnProperties const & getProperties (std::size_t pos) const;
ColumnProperties const & getProperties (std::string const &name) const;
template <typename T>
T get(std::size_t pos) const
{
typedef typename TypeConversion<T>::base_type BASE_TYPE;
assert(holders_.size() >= pos + 1);
if (eNull == *indicators_[pos])
{
throw SOCIError("Column contains NULL value and"
" no default was provided");
}
BASE_TYPE baseVal = holders_[pos]->get<BASE_TYPE>();
return TypeConversion<T>::from(baseVal);
}
template <typename T>
T get(std::size_t pos, T const &nullValue) const
{
assert(holders_.size() >= pos + 1);
if (eNull == *indicators_[pos])
{
return nullValue;
}
return get<T>(pos);
}
template <typename T>
T get(std::string const &name) const
{
std::size_t pos = findColumn(name);
if (eNull == *indicators_[pos])
{
throw SOCIError("Column '" + name + "' contains NULL value and"
" no default was provided")
;
}
return get<T>(pos);
}
template <typename T>
T get(std::string const &name, T const &nullValue) const
{
std::size_t pos = findColumn(name);
if (eNull == *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 resetGetCounter()
{
currentPos_ = 0;
}
Row() : currentPos_(0) {}
~Row();
private:
// copy not supported
Row(Row const &);
Row operator=(Row const &);
std::size_t findColumn(std::string const &name) const;
std::vector<ColumnProperties> columns_;
std::vector<details::Holder*> holders_;
std::vector<eIndicator*> indicators_;
std::map<std::string, std::size_t> index_;
mutable std::size_t currentPos_;
};
namespace details
{
class PrepareTempType;
} // namespace details
class Values;
namespace details
{
class SOCI_DECL StatementImpl
{
public:
StatementImpl(Session &s);
StatementImpl(details::PrepareTempType const &prep);
~StatementImpl();
void alloc();
void bind(Values& values);
void exchange(details::IntoTypePtr const &i);
void exchange(details::UseTypePtr const &u);
void cleanUp();
void prepare(std::string const &query,
details::eStatementType eType = details::eRepeatableQuery);
void defineAndBind();
void unDefAndBind();
bool execute(bool withDataExchange = false);
bool fetch();
void describe();
void setRow(Row* r);
void exchangeForRowset(details::IntoTypePtr const &i);
// for diagnostics and advanced users
// (downcast it to expected back-end statement class)
details::StatementBackEnd * getBackEnd() { return backEnd_; }
details::StandardIntoTypeBackEnd * makeIntoTypeBackEnd();
details::StandardUseTypeBackEnd * makeUseTypeBackEnd();
details::VectorIntoTypeBackEnd * makeVectorIntoTypeBackEnd();
details::VectorUseTypeBackEnd * makeVectorUseTypeBackEnd();
void incRef();
void decRef();
Session &session_;
std::string rewriteForProcedureCall(std::string const &query);
protected:
std::vector<details::IntoTypeBase*> intos_;
std::vector<details::UseTypeBase*> uses_;
std::vector<eIndicator*> indicators_;
private:
int refCount_;
Row* row_;
std::size_t fetchSize_;
std::size_t initialFetchSize_;
std::string query_;
std::map<std::string, details::UseTypeBase*> namedUses_;
std::vector<details::IntoTypeBase*> intosForRow_;
int definePositionForRow_;
void exchangeForRow(details::IntoTypePtr const &i);
void defineForRow();
template<typename T>
void intoRow()
{
T* t = new T();
eIndicator* ind = new eIndicator(eOK);
row_->addHolder(t, ind);
exchangeForRow(into(*t, *ind));
}
template<eDataType> void bindInto();
bool alreadyDescribed_;
std::size_t intosSize();
std::size_t usesSize();
void preFetch();
void preUse();
void postFetch(bool gotData, bool calledFromFetch);
void postUse(bool gotData);
bool resizeIntos(std::size_t upperBound = 0);
details::StatementBackEnd *backEnd_;
};
} // namespace details
// Statement is a handle class for StatementImpl
// (this provides copyability to otherwise non-copyable type)
class SOCI_DECL Statement
{
public:
Statement(Session &s)
: impl_(new details::StatementImpl(s)) {}
Statement(details::PrepareTempType const &prep)
: impl_(new details::StatementImpl(prep)) {}
~Statement() { impl_->decRef(); }
// copy is supported for this handle class
Statement(Statement const &other)
: impl_(other.impl_)
{
impl_->incRef();
}
void operator=(Statement const &other)
{
other.impl_->incRef();
impl_->decRef();
impl_ = other.impl_;
}
void alloc() { impl_->alloc(); }
void bind(Values& values) { impl_->bind(values); }
void exchange(details::IntoTypePtr const &i) { impl_->exchange(i); }
void exchange(details::UseTypePtr const &u) { impl_->exchange(u); }
void cleanUp() { impl_->cleanUp(); }
void prepare(std::string const &query,
details::eStatementType eType = details::eRepeatableQuery)
{
impl_->prepare(query, eType);
}
void defineAndBind() { impl_->defineAndBind(); }
void unDefAndBind() { impl_->unDefAndBind(); }
bool execute(bool withDataExchange = false)
{
return impl_->execute(withDataExchange);
}
bool fetch() { return impl_->fetch(); }
void describe() { impl_->describe(); }
void setRow(Row* r) { impl_->setRow(r); }
void exchangeForRowset(details::IntoTypePtr const &i)
{
impl_->exchangeForRowset(i);
}
// for diagnostics and advanced users
// (downcast it to expected back-end statement class)
details::StatementBackEnd * getBackEnd()
{
return impl_->getBackEnd();
}
details::StandardIntoTypeBackEnd * makeIntoTypeBackEnd()
{
return impl_->makeIntoTypeBackEnd();
}
details::StandardUseTypeBackEnd * makeUseTypeBackEnd()
{
return impl_->makeUseTypeBackEnd();
}
details::VectorIntoTypeBackEnd * makeVectorIntoTypeBackEnd()
{
return impl_->makeVectorIntoTypeBackEnd();
}
details::VectorUseTypeBackEnd * makeVectorUseTypeBackEnd()
{
return impl_->makeVectorUseTypeBackEnd();
}
std::string rewriteForProcedureCall(std::string const &query)
{
return impl_->rewriteForProcedureCall(query);
}
private:
details::StatementImpl * impl_;
};
namespace details
{
class ProcedureImpl : public StatementImpl
{
public:
ProcedureImpl(Session &s) : StatementImpl(s), refCount_(1) {}
ProcedureImpl(details::PrepareTempType const &prep);
void incRef() { ++refCount_; }
void decDef()
{
if (--refCount_)
{
delete this;
}
}
private:
int refCount_;
};
} // namespace details
class SOCI_DECL Procedure
{
public:
Procedure(Session &s)
: impl_(new details::ProcedureImpl(s)) {}
Procedure(details::PrepareTempType const &prep)
: impl_(new details::ProcedureImpl(prep)) {}
~Procedure() { impl_->decRef(); }
// copy is supported here
Procedure(Procedure const &other)
: impl_(other.impl_)
{
impl_->incRef();
}
void operator=(Procedure const &other)
{
other.impl_->incRef();
impl_->decRef();
impl_ = other.impl_;
}
// forwarders to ProcedureImpl
// (or rather to its base interface from StatementImpl)
bool execute(bool withDataExchange = false)
{
return impl_->execute(withDataExchange);
}
bool fetch()
{
return impl_->fetch();
}
private:
details::ProcedureImpl * impl_;
};
namespace details
{
// this class is a base for both "once" and "prepare" statements
class RefCountedStBase
{
public:
RefCountedStBase() : refCount_(1) {}
virtual ~RefCountedStBase() {}
virtual void finalAction() = 0;
void incRef() { ++refCount_; }
void decRef()
{
if (--refCount_ == 0)
{
try
{
finalAction();
}
catch (...)
{
delete this;
throw;
}
delete this;
}
}
// TODO - mloskot: Consider to wrap conversion with try-catch
template <typename T>
void accumulate(T const &t) { query_ << t; }
protected:
RefCountedStBase(RefCountedStBase const &);
RefCountedStBase & operator=(RefCountedStBase const &);
int refCount_;
std::ostringstream query_;
};
// this class is supposed to be a vehicle for the "once" statements
// it executes the whole statement in its destructor
class RefCountedStatement : public RefCountedStBase
{
public:
RefCountedStatement(Session &s) : st_(s) {}
void exchange(IntoTypePtr const &i) { st_.exchange(i); }
void exchange(UseTypePtr const &u) { st_.exchange(u); }
virtual void finalAction();
private:
Statement st_;
};
// this class conveys only the statement text and the bind/define info
// it exists only to be passed to Statement's constructor
class RefCountedPrepareInfo : public RefCountedStBase
{
public:
RefCountedPrepareInfo(Session &s) : session_(&s) {}
void exchange(IntoTypePtr const &i);
void exchange(UseTypePtr const &u);
virtual void finalAction();
private:
friend class SOCI::details::StatementImpl;
friend class SOCI::details::ProcedureImpl;
Session *session_;
std::vector<IntoTypeBase*> intos_;
std::vector<UseTypeBase*> uses_;
std::string getQuery() const { return query_.str(); }
};
// this needs to be lightweight and copyable
class SOCI_DECL PrepareTempType
{
public:
PrepareTempType(Session &);
PrepareTempType(PrepareTempType const &);
PrepareTempType & operator=(PrepareTempType const &);
~PrepareTempType();
template <typename T>
PrepareTempType & operator<<(T const &t)
{
rcpi_->accumulate(t);
return *this;
}
PrepareTempType & operator,(IntoTypePtr const &i);
PrepareTempType & operator,(UseTypePtr const &u);
RefCountedPrepareInfo * getPrepareInfo() const { return rcpi_; }
private:
RefCountedPrepareInfo *rcpi_;
};
// this needs to be lightweight and copyable
class SOCI_DECL OnceTempType
{
public:
OnceTempType(Session &s);
OnceTempType(OnceTempType const &o);
OnceTempType & operator=(OnceTempType const &o);
~OnceTempType();
template <typename T>
OnceTempType & operator<<(T const &t)
{
rcst_->accumulate(t);
return *this;
}
OnceTempType & operator,(IntoTypePtr const &);
OnceTempType & operator,(UseTypePtr const &);
private:
RefCountedStatement *rcst_;
};
// this needs to be lightweight and copyable
class OnceType
{
public:
OnceType(Session *s) : session_(s) {}
template <typename T>
OnceTempType operator<<(T const &t)
{
OnceTempType o(*session_);
o << t;
return o;
}
private:
Session *session_;
};
// this needs to be lightweight and copyable
class PrepareType
{
public:
PrepareType(Session *s) : session_(s) {}
template <typename T>
PrepareTempType operator<<(T const &t)
{
PrepareTempType p(*session_);
p << t;
return p;
}
private:
Session *session_;
};
} // namespace details
class SOCI_DECL Session
{
public:
Session(BackEndFactory const &factory, std::string const & connectStrin
g);
~Session();
void begin();
void commit();
void rollback();
// once and prepare are for syntax sugar only
details::OnceType once;
details::PrepareType prepare;
// even more sugar
template <typename T>
details::OnceTempType operator<<(T const &t) { return once << t; }
// support for basic logging
void setLogStream(std::ostream *s);
std::ostream * getLogStream() const;
void logQuery(std::string const &query);
std::string getLastQuery() const;
// for diagnostics and advanced users
// (downcast it to expected back-end session class)
details::SessionBackEnd * getBackEnd() { return backEnd_; }
details::StatementBackEnd * makeStatementBackEnd();
details::RowIDBackEnd * makeRowIDBackEnd();
details::BLOBBackEnd * makeBLOBBackEnd();
private:
Session(Session const &);
Session& operator=(Session const &);
std::ostream *logStream_;
std::string lastQuery_;
details::SessionBackEnd *backEnd_;
};
namespace details
{
// template specializations for bind and define operations
// standard types
class SOCI_DECL StandardIntoType : public IntoTypeBase
{
public:
StandardIntoType(void *data, eExchangeType type)
: data_(data), type_(type), ind_(NULL), backEnd_(NULL) {}
StandardIntoType(void *data, eExchangeType type, eIndicator& ind)
: data_(data), type_(type), ind_(&ind), backEnd_(NULL) {}
virtual ~StandardIntoType();
private:
virtual void define(StatementImpl &st, int &position);
virtual void preFetch();
virtual void postFetch(bool gotData, bool calledFromFetch);
virtual void cleanUp();
virtual std::size_t size() const { return 1; }
// conversion hook (from base type to arbitrary user type)
virtual void convertFrom() {}
void *data_;
eExchangeType type_;
eIndicator *ind_;
details::StandardIntoTypeBackEnd *backEnd_;
};
class SOCI_DECL StandardUseType : public UseTypeBase
{
public:
StandardUseType(void *data, eExchangeType type,
std::string const &name = std::string())
: data_(data), type_(type), ind_(NULL), name_(name), backEnd_(NULL)
{}
StandardUseType(void *data, eExchangeType type, eIndicator &ind,
std::string const &name = std::string())
: data_(data), type_(type), ind_(&ind), name_(name), backEnd_(NULL)
{}
virtual ~StandardUseType();
virtual void bind(details::StatementImpl &st, int &position);
std::string getName() const {return name_;}
virtual void* getData() {return data_;}
// conversion hook (from arbitrary user type to base type)
virtual void convertTo() {}
virtual void convertFrom() {}
private:
virtual void preUse();
virtual void postUse(bool gotData);
virtual void cleanUp();
virtual std::size_t size() const { return 1; }
void *data_;
eExchangeType type_;
eIndicator *ind_;
std::string name_;
details::StandardUseTypeBackEnd *backEnd_;
};
// into and use type base classes for vectors
class SOCI_DECL VectorIntoType : public IntoTypeBase
{
public:
VectorIntoType(void *data, eExchangeType type)
: data_(data), type_(type), indVec_(NULL), backEnd_(NULL) {}
VectorIntoType(void *data, eExchangeType type,
std::vector<eIndicator> &ind)
: data_(data), type_(type), indVec_(&ind), backEnd_(NULL) {}
~VectorIntoType();
private:
virtual void define(details::StatementImpl &st, int &position);
virtual void preFetch();
virtual void postFetch(bool gotData, bool calledFromFetch);
virtual void cleanUp();
virtual void resize(std::size_t sz);
virtual std::size_t size() const;
void *data_;
eExchangeType type_;
std::vector<eIndicator> *indVec_;
details::VectorIntoTypeBackEnd *backEnd_;
virtual void convertFrom() {}
};
class SOCI_DECL VectorUseType : public UseTypeBase
{
public:
VectorUseType(void *data, eExchangeType type,
std::string const &name = std::string())
: data_(data), type_(type), ind_(NULL),
name_(name), backEnd_(NULL) {}
VectorUseType(void *data, eExchangeType type,
std::vector<eIndicator> const &ind,
std::string const &name = std::string())
: data_(data), type_(type), ind_(&ind.at(0)),
name_(name), backEnd_(NULL) {}
~VectorUseType();
private:
virtual void bind(details::StatementImpl &st, int &position);
virtual void preUse();
virtual void postUse(bool) { /* nothing to do */ }
virtual void cleanUp();
virtual std::size_t size() const;
void *data_;
eExchangeType type_;
eIndicator const *ind_;
std::string name_;
details::VectorUseTypeBackEnd *backEnd_;
virtual void convertTo() {}
};
// into and use types for short
template <>
class IntoType<short> : public StandardIntoType
{
public:
IntoType(short &s) : StandardIntoType(&s, eXShort) {}
IntoType(short &s, eIndicator &ind)
: StandardIntoType(&s, eXShort, ind) {}
};
template <>
class UseType<short> : public StandardUseType
{
public:
UseType(short &s, std::string const &name = std::string())
: StandardUseType(&s, eXShort, name) {}
UseType(short &s, eIndicator &ind,
std::string const &name = std::string())
: StandardUseType(&s, eXShort, ind, name) {}
};
// into and use types for std::vector<short>
template <>
class IntoType<std::vector<short> > : public VectorIntoType
{
public:
IntoType(std::vector<short> &v) : VectorIntoType(&v, eXShort) {}
IntoType(std::vector<short> &v, std::vector<eIndicator> &ind)
: VectorIntoType(&v, eXShort, ind) {}
};
template <>
class UseType<std::vector<short> > : public VectorUseType
{
public:
UseType(std::vector<short> &v, std::string const &name = std::string())
: VectorUseType(&v, eXShort, name) {}
UseType(std::vector<short> &v, std::vector<eIndicator> const &ind,
std::string const &name = std::string())
: VectorUseType(&v, eXShort, ind, name) {}
};
// into and use types for int
template <>
class IntoType<int> : public StandardIntoType
{
public:
IntoType(int &i) : StandardIntoType(&i, eXInteger) {}
IntoType(int &i, eIndicator &ind)
: StandardIntoType(&i, eXInteger, ind) {}
};
template <>
class UseType<int> : public StandardUseType
{
public:
UseType(int &i, std::string const &name = std::string())
: StandardUseType(&i, eXInteger, name) {}
UseType(int &i, eIndicator &ind,
std::string const &name = std::string())
: StandardUseType(&i, eXInteger, ind, name) {}
};
// into and use types for std::vector<int>
template <>
class IntoType<std::vector<int> > : public VectorIntoType
{
public:
IntoType(std::vector<int> &v) : VectorIntoType(&v, eXInteger) {}
IntoType(std::vector<int> &v, std::vector<eIndicator> &ind)
: VectorIntoType(&v, eXInteger, ind) {}
};
template <>
class UseType<std::vector<int> > : public VectorUseType
{
public:
UseType(std::vector<int> &v, std::string const &name = std::string())
: VectorUseType(&v, eXInteger, name) {}
UseType(std::vector<int> &v, std::vector<eIndicator> const &ind,
std::string const &name = std::string())
: VectorUseType(&v, eXInteger, ind, name) {}
};
// into and use types for char
template <>
class IntoType<char> : public StandardIntoType
{
public:
IntoType(char &c) : StandardIntoType(&c, eXChar) {}
IntoType(char &c, eIndicator &ind)
: StandardIntoType(&c, eXChar, ind) {}
};
template <>
class UseType<char> : public StandardUseType
{
public:
UseType(char &c, std::string const &name = std::string())
: StandardUseType(&c, eXChar, name) {}
UseType(char &c, eIndicator &ind,
std::string const &name = std::string())
: StandardUseType(&c, eXChar, ind, name) {}
};
// into and use types for std::vector<char>
template <>
class IntoType<std::vector<char> >: public VectorIntoType
{
public:
IntoType(std::vector<char> &v) : VectorIntoType(&v, eXChar) {}
IntoType(std::vector<char> &v, std::vector<eIndicator> &vind)
: VectorIntoType(&v, eXChar, vind) {}
};
template <>
class UseType<std::vector<char> >: public VectorUseType
{
public:
UseType(std::vector<char> &v, std::string const &name = std::string())
: VectorUseType(&v, eXChar, name) {}
UseType(std::vector<char> &v, std::vector<eIndicator> const &vind,
std::string const &name = std::string())
: VectorUseType(&v, eXChar, vind, name) {}
};
// into and use types for unsigned long
template <>
class IntoType<unsigned long> : public StandardIntoType
{
public:
IntoType(unsigned long &ul) : StandardIntoType(&ul, eXUnsignedLong) {}
IntoType(unsigned long &ul, eIndicator &ind)
: StandardIntoType(&ul, eXUnsignedLong, ind) {}
};
template <>
class UseType<unsigned long> : public StandardUseType
{
public:
UseType(unsigned long &ul, std::string const &name = std::string())
: StandardUseType(&ul, eXUnsignedLong, name) {}
UseType(unsigned long &ul, eIndicator &ind,
std::string const &name = std::string())
: StandardUseType(&ul, eXUnsignedLong, ind, name) {}
};
template <>
class IntoType<std::vector<unsigned long> > : public VectorIntoType
{
public:
IntoType(std::vector<unsigned long> &v)
: VectorIntoType(&v, eXUnsignedLong) {}
IntoType(std::vector<unsigned long> &v, std::vector<eIndicator> &vind)
: VectorIntoType(&v, eXUnsignedLong, vind) {}
};
template <>
class UseType<std::vector<unsigned long> > : public VectorUseType
{
public:
UseType(std::vector<unsigned long> &v,
std::string const &name = std::string())
: VectorUseType(&v, eXUnsignedLong, name) {}
UseType(std::vector<unsigned long> &v,
std::vector<eIndicator> const &ind,
std::string const &name = std::string())
: VectorUseType(&v, eXUnsignedLong, ind, name) {}
};
// into and use types for double
template <>
class IntoType<double> : public StandardIntoType
{
public:
IntoType(double &d) : StandardIntoType(&d, eXDouble) {}
IntoType(double &d, eIndicator &ind)
: StandardIntoType(&d, eXDouble, ind) {}
};
template <>
class UseType<double> : public StandardUseType
{
public:
UseType(double &d, std::string const &name = std::string())
: StandardUseType(&d, eXDouble, name) {}
UseType(double &d, eIndicator &ind,
std::string const &name = std::string())
: StandardUseType(&d, eXDouble, ind, name) {}
};
// into and use types for std::vector<double>
template <>
class IntoType<std::vector<double> > : public VectorIntoType
{
public:
IntoType(std::vector<double> &v)
: VectorIntoType(&v, eXDouble) {}
IntoType(std::vector<double> &v, std::vector<eIndicator> &vind)
: VectorIntoType(&v, eXDouble, vind) {}
};
template <>
class UseType<std::vector<double> > : public VectorUseType
{
public:
UseType(std::vector<double> &v, std::string const &name = std::string()
)
: VectorUseType(&v, eXDouble, name) {}
UseType(std::vector<double> &v, std::vector<eIndicator> const &ind,
std::string const &name = std::string())
: VectorUseType(&v, eXDouble, ind, name) {}
};
// into and use types for char*
template <>
class IntoType<char*> : public StandardIntoType
{
public:
IntoType(char *str, std::size_t bufSize)
: StandardIntoType(&str_, eXCString), str_(str, bufSize) {}
IntoType(char *str, eIndicator &ind, std::size_t bufSize)
: StandardIntoType(&str_, eXCString, ind), str_(str, bufSize) {}
private:
CStringDescriptor str_;
};
template <>
class UseType<char*> : public StandardUseType
{
public:
UseType(char *str, std::size_t bufSize,
std::string const &name = std::string())
: StandardUseType(&str_, eXCString, name), str_(str, bufSize) {}
UseType(char *str, eIndicator &ind, std::size_t bufSize,
std::string const &name = std::string())
: StandardUseType(&str_, eXCString, ind, name), str_(str, bufSize)
{}
private:
CStringDescriptor str_;
};
// into and use types for char arrays (with size known at compile-time)
template <std::size_t N>
class IntoType<char[N]> : public IntoType<char*>
{
public:
IntoType(char str[]) : IntoType<char*>(str, N) {}
IntoType(char str[], eIndicator &ind) : IntoType<char*>(str, ind, N) {}
};
template <std::size_t N>
class UseType<char[N]> : public UseType<char*>
{
public:
UseType(char str[], std::string const &name = std::string())
: UseType<char*>(str, N, name) {}
UseType(char str[], eIndicator &ind,
std::string const &name = std::string())
: UseType<char*>(str, ind, N, name) {}
};
// into and use types for std::string
template <>
class IntoType<std::string> : public StandardIntoType
{
public:
IntoType(std::string &s) : StandardIntoType(&s, eXStdString) {}
IntoType(std::string &s, eIndicator &ind)
: StandardIntoType(&s, eXStdString, ind) {}
};
template <>
class UseType<std::string> : public StandardUseType
{
public:
UseType(std::string &s, std::string const &name = std::string())
: StandardUseType(&s, eXStdString, name) {}
UseType(std::string &s, eIndicator &ind,
std::string const &name = std::string())
: StandardUseType(&s, eXStdString, ind, name) {}
};
// into and use types for std::vector<std::string>
template <>
class IntoType<std::vector<std::string> > : public VectorIntoType
{
public:
IntoType(std::vector<std::string>& v)
: VectorIntoType(&v, eXStdString) {}
IntoType(std::vector<std::string>& v, std::vector<eIndicator> &vind)
: VectorIntoType(&v, eXStdString, vind) {}
};
template <>
class UseType<std::vector<std::string> > : public VectorUseType
{
public:
UseType(std::vector<std::string>& v,
std::string const &name = std::string())
: VectorUseType(&v, eXStdString, name) {}
UseType(std::vector<std::string>& v, std::vector<eIndicator> const &ind
,
std::string const &name = std::string())
: VectorUseType(&v, eXStdString, ind, name) {}
};
// into and use types for date and time (struct tm)
template <>
class IntoType<std::tm> : public StandardIntoType
{
public:
IntoType(std::tm &t) : StandardIntoType(&t, eXStdTm) {}
IntoType(std::tm &t, eIndicator &ind)
: StandardIntoType(&t, eXStdTm, ind) {}
};
template <>
class UseType<std::tm> : public StandardUseType
{
public:
UseType(std::tm &t, std::string const &name = std::string())
: StandardUseType(&t, eXStdTm, name) {}
UseType(std::tm &t, eIndicator &ind,
std::string const &name = std::string())
: StandardUseType(&t, eXStdTm, ind, name) {}
};
// into and use types for std::vector<std::tm>
template <>
class IntoType<std::vector<std::tm> > : public VectorIntoType
{
public:
IntoType(std::vector<std::tm>& v) : VectorIntoType(&v, eXStdTm) {}
IntoType(std::vector<std::tm>& v, std::vector<eIndicator> &vind)
: VectorIntoType(&v, eXStdTm, vind) {}
};
template <>
class UseType<std::vector<std::tm> > : public VectorUseType
{
public:
UseType(std::vector<std::tm>& v, std::string const &name = std::string(
))
: VectorUseType(&v, eXStdTm, name) {}
UseType(std::vector<std::tm>& v, std::vector<eIndicator> const &vind,
std::string const &name = std::string())
: VectorUseType(&v, eXStdTm, vind, name) {}
};
// into and use types for Statement (for nested statements and cursors)
template <>
class IntoType<Statement> : public StandardIntoType
{
public:
IntoType(Statement &s) : StandardIntoType(&s, eXStatement) {}
IntoType(Statement &s, eIndicator &ind)
: StandardIntoType(&s, eXStatement, ind) {}
};
template <>
class UseType<Statement> : public StandardUseType
{
public:
UseType(Statement &s, std::string const &name = std::string())
: StandardUseType(&s, eXStatement, name) {}
UseType(Statement &s, eIndicator &ind,
std::string const &name = std::string())
: StandardUseType(&s, eXStatement, ind, name) {}
};
// Support selecting into a Row for dynamic queries
template <>
class IntoType<Row> : public IntoTypeBase // bypass the StandardIntoType
{
public:
IntoType(Row &r) : r_(r) {}
private:
// special handling for Row
virtual void define(details::StatementImpl &st, int & /* position */)
{
st.setRow(&r_);
// actual row description is performed
// as part of the statement execute
}
virtual void preFetch() {}
virtual void postFetch(bool gotData, bool /* calledFromFetch */)
{
r_.resetGetCounter();
if (gotData)
{
// this is used only to re-dispatch to derived class, if any
// (the derived class might be generated automatically by
// user conversions)
convertFrom();
}
}
virtual void cleanUp() {}
virtual std::size_t size() const { return 1; }
virtual void convertFrom() {}
Row &r_;
};
// this class is used to ensure correct order of construction
// of IntoType and UseType elements that use TypeConversion (later)
template <typename T>
struct BaseValueHolder
{
typename TypeConversion<T>::base_type val_;
};
template <typename T>
struct BaseVectorHolder
{
BaseVectorHolder(std::size_t sz = 0) : vec_(sz) {}
std::vector<typename TypeConversion<T>::base_type> vec_;
};
// Automatically create an IntoType from a TypeConversion
template <typename T>
class IntoType
: private details::BaseValueHolder<T>,
public IntoType<typename TypeConversion<T>::base_type>
{
public:
typedef typename TypeConversion<T>::base_type BASE_TYPE;
IntoType(T &value)
: IntoType<BASE_TYPE>(details::BaseValueHolder<T>::val_),
value_(value) {}
IntoType(T &value, eIndicator &ind)
: IntoType<BASE_TYPE>(details::BaseValueHolder<T>::val_, ind),
value_(value) {}
private:
void convertFrom()
{
value_ = TypeConversion<T>::from(details::BaseValueHolder<T>::val_)
;
}
T &value_;
};
// Automatically create a UseType from a TypeConversion
template <typename T>
class UseType
: private details::BaseValueHolder<T>,
public UseType<typename TypeConversion<T>::base_type>
{
public:
typedef typename TypeConversion<T>::base_type BASE_TYPE;
UseType(T &value, std::string const &name = std::string())
: UseType<BASE_TYPE>(details::BaseValueHolder<T>::val_, name),
value_(value) {}
UseType(T &value, eIndicator &ind, std::string const &name
= std::string())
: UseType<BASE_TYPE>(details::BaseValueHolder<T>::val_, ind, name),
value_(value) {}
virtual void* getData()
{
convertFrom();
return &value_;
}
void convertFrom()
{
value_ = TypeConversion<T>::from(details::BaseValueHolder<T>::val_)
;
}
void convertTo()
{
details::BaseValueHolder<T>::val_ = TypeConversion<T>::to(value_);
}
private:
T &value_;
};
// Automatically create a std::vector based IntoType from a TypeConversion
template <typename T>
class IntoType<std::vector<T> >
: private details::BaseVectorHolder<T>,
public IntoType<std::vector<typename TypeConversion<T>::base_type> >
{
public:
typedef typename std::vector<typename TypeConversion<T>::base_type>
BASE_TYPE;
IntoType(std::vector<T> &value)
: details::BaseVectorHolder<T>(value.size()),
IntoType<BASE_TYPE>(details::BaseVectorHolder<T>::vec_),
value_(value) {}
IntoType(std::vector<T> &value, std::vector<eIndicator> &ind)
: details::BaseVectorHolder<T>(value.size()),
IntoType<BASE_TYPE>(details::BaseVectorHolder<T>::vec_, ind),
value_(value) {}
virtual std::size_t size() const
{
return details::BaseVectorHolder<T>::vec_.size();
}
virtual void resize(std::size_t sz)
{
value_.resize(sz);
details::BaseVectorHolder<T>::vec_.resize(sz);
}
private:
void convertFrom()
{
std::size_t const sz = details::BaseVectorHolder<T>::vec_.size();
for (std::size_t i = 0; i != sz; ++i)
{
value_[i] = TypeConversion<T>::from(
details::BaseVectorHolder<T>::vec_[i]);
}
}
std::vector<T> &value_;
};
// Automatically create a std::vector based UseType from a TypeConversion
template <typename T>
class UseType<std::vector<T> >
: private details::BaseVectorHolder<T>,
public UseType<std::vector<typename TypeConversion<T>::base_type> >
{
public:
typedef typename std::vector<typename TypeConversion<T>::base_type>
BASE_TYPE;
UseType(std::vector<T> &value)
: details::BaseVectorHolder<T>(value.size()),
UseType<BASE_TYPE>(details::BaseVectorHolder<T>::vec_),
value_(value) {}
UseType(std::vector<T> &value, std::vector<eIndicator> const &ind,
std::string const &name=std::string())
: details::BaseVectorHolder<T>(value.size()),
UseType<BASE_TYPE>(details::BaseVectorHolder<T>::vec_, ind, name)
,
value_(value) {}
private:
void convertFrom()
{
std::size_t const sz = details::BaseVectorHolder<T>::vec_.size();
for (std::size_t i = 0; i != sz; ++i)
{
value_[i] = TypeConversion<T>::from(
details::BaseVectorHolder<T>::vec_[i]);
}
}
void convertTo()
{
std::size_t const sz = value_.size();
for (std::size_t i = 0; i != sz; ++i)
{
details::BaseVectorHolder<T>::vec_[i]
= TypeConversion<T>::to(value_[i]);
}
}
std::vector<T> &value_;
};
} // namespace details
class SOCI_DECL Values
{
friend class details::StatementImpl;
friend class details::IntoType<Values>;
friend class details::UseType<Values>;
public:
Values() : row_(NULL), currentPos_(0) {}
eIndicator indicator(std::size_t pos) const;
eIndicator indicator(std::string const &name) const;
template <typename T>
T get(std::size_t pos) const
{
if (row_)
{
return row_->get<T>(pos);
}
else if (*indicators_[pos] != eNull)
{
return getFromUses<T>(pos);
}
else
{
std::ostringstream msg;
msg << "Column at position "
<< static_cast<unsigned long>(pos)
<< " contains NULL value and no default was provided";
throw SOCIError(msg.str());
}
}
template <typename T>
T get(std::size_t pos, T const &nullValue) const
{
if (row_)
{
return row_->get<T>(pos, nullValue);
}
else if (*indicators_[pos] == eNull)
{
return nullValue;
}
else
{
return getFromUses<T>(pos);
}
}
template <typename T>
T get(std::string const &name) const
{
return row_ ? row_->get<T>(name) : getFromUses<T>(name);
}
template <typename T>
T get(std::string const &name, T const &nullValue) const
{
return row_ ? row_->get<T>(name, nullValue)
: getFromUses<T>(name, nullValue);
}
template <typename T>
Values const & operator>>(T &value) const
{
value = row_->get<T>(currentPos_);
++currentPos_;
return *this;
}
template <typename T>
void set(std::string const &name, T &value, eIndicator indicator=eOK)
{
index_.insert(std::make_pair(name, uses_.size()));
eIndicator* ind = new eIndicator(indicator);
uses_.push_back(new details::UseType<T>(value, *ind, name));
indicators_.push_back(ind);
}
private:
//TODO To make Values generally usable outside of TypeConversionS,
// these should be reference counted smart pointers
Row *row_;
std::vector<details::StandardUseType*> uses_;
std::map<details::UseTypeBase*, eIndicator*> unused_;
std::vector<eIndicator*> indicators_;
std::map<std::string, size_t> index_;
// When TypeConversion::to() is called, a Values object is created
// without an underlying Row object. In that case, getFromUses()
// returns the underlying field values
template <typename T>
T getFromUses(std::string const &name, T const &nullValue) const
{
std::map<std::string, size_t>::const_iterator pos = index_.find(nam
e);
if (pos != index_.end())
{
if (*indicators_[pos->second] == eNull)
{
return nullValue;
}
try
{
return getFromUses<T>(pos->second);
}
catch(SOCIError const &)
{
throw SOCIError("Value named " + name + " was set using"
" a different type than the one passed to get()");
}
}
throw SOCIError("Value named " + name + " not found.");
}
template <typename T>
T getFromUses(std::string const &name) const
{
std::map<std::string, size_t>::const_iterator pos = index_.find(nam
e);
if (pos != index_.end())
{
if (*indicators_[pos->second] == eNull)
{
throw SOCIError("Column " + name + " contains NULL value an
d"
" no default was provided");
}
try
{
return getFromUses<T>(pos->second);
}
catch(SOCIError const &)
{
throw SOCIError("Value named " + name + " was set using"
" a different type than the one passed to get()");
}
}
throw SOCIError("Value named " + name + " not found.");
}
template <typename T>
T getFromUses(size_t pos) const
{
details::StandardUseType* u = uses_[pos];
if (dynamic_cast<details::UseType<T>* >(u))
{
return *static_cast<T*>(u->getData());
}
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 SOCIError(msg.str());
}
}
Row& getRow()
{
row_ = new Row();
return *row_;
}
// this is called by Statement::bind(Values)
void addUnused(details::UseTypeBase *u, eIndicator *i)
{
static_cast<details::StandardUseType*>(u)->convertTo();
unused_.insert(std::make_pair(u, i));
}
// this is called by details::IntoType<Values>::cleanUp()
// and UseType<Values>::cleanUp()
void cleanUp()
{
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::cleanUp())
for (std::map<details::UseTypeBase*, eIndicator*>::iterator pos =
unused_.begin(); pos != unused_.end(); ++pos)
{
delete pos->first;
delete pos->second;
}
}
mutable std::size_t currentPos_;
};
namespace details
{
template <>
class IntoType<Values> : public IntoType<Row>
{
public:
IntoType(Values &v) :
IntoType<Row>(v.getRow()), v_(v) {}
void cleanUp()
{
v_.cleanUp();
}
private:
Values &v_;
};
template <>
class UseType<Values> : public UseTypeBase
{
public:
UseType(Values &v, std::string const & /* name */ = std::string())
: v_(v) {}
virtual void bind(details::StatementImpl &st, int& /*position*/)
{
convertTo();
st.bind(v_);
}
virtual void postUse(bool /*gotData*/)
{
convertFrom();
}
virtual void preUse() {}
virtual void cleanUp() {v_.cleanUp();}
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 convertTo() {}
virtual void convertFrom() {}
private:
Values& v_;
};
} // namespace details
// basic BLOB operations
class SOCI_DECL BLOB
{
public:
BLOB(Session &s);
~BLOB();
std::size_t getLen();
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::BLOBBackEnd * getBackEnd() { return backEnd_; }
private:
details::BLOBBackEnd *backEnd_;
};
namespace details
{
template <>
class IntoType<BLOB> : public StandardIntoType
{
public:
IntoType(BLOB &b) : StandardIntoType(&b, eXBLOB) {}
IntoType(BLOB &b, eIndicator &ind)
: StandardIntoType(&b, eXBLOB, ind) {}
};
template <>
class UseType<BLOB> : public StandardUseType
{
public:
UseType(BLOB &b, std::string const &name = std::string())
: StandardUseType(&b, eXBLOB, name) {}
UseType(BLOB &b, eIndicator &ind,
std::string const &name = std::string())
: StandardUseType(&b, eXBLOB, ind, name) {}
};
} // namespace details
// ROWID support
class SOCI_DECL RowID
{
public:
RowID(Session &s);
~RowID();
details::RowIDBackEnd * getBackEnd() { return backEnd_; }
private:
details::RowIDBackEnd *backEnd_;
};
namespace details
{
template <>
class IntoType<RowID> : public StandardIntoType
{
public:
IntoType(RowID &rid) : StandardIntoType(&rid, eXRowID) {}
IntoType(RowID &rid, eIndicator &ind)
:StandardIntoType(&rid, eXRowID, ind) {}
};
template <>
class UseType<RowID> : public StandardUseType
{
public:
UseType(RowID &rid, std::string const &name = std::string())
: StandardUseType(&rid, eXRowID, name) {}
UseType(RowID &rid, eIndicator &ind,
std::string const &name = std::string())
: StandardUseType(&rid, eXRowID, ind, name) {}
};
} // namespace details
//
// 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)
{
assert(0 != st_);
assert(0 != define_);
assert(0 != st_->getBackEnd());
// 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())
{
// 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));
}
private:
// TODO - mloskot: think about weak_ptr here, an observer concept
Statement* st_;
T* define_;
}; // class rowset_iterator
namespace details
{
//
// Implementation of Rowset
//
template <typename T>
class RowsetImpl
{
public:
typedef rowset_iterator<T> iterator;
RowsetImpl(details::PrepareTempType const& prep)
: refs_(1), st_(new Statement(prep)), define_(new T())
{
assert(0 != st_.get());
assert(0 != define_.get());
st_->exchangeForRowset(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_;
const std::auto_ptr<Statement> st_;
const std::auto_ptr<T> define_;
// Non-copyable
RowsetImpl(RowsetImpl const&);
RowsetImpl& operator=(RowsetImpl const&);
}; // class RowsetImpl
} // namespace details
//
// Rowset is a thin wrapper on Statement and provides access to STL-like in
put 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;
Rowset(details::PrepareTempType const& prep)
: pimpl_(new details::RowsetImpl<T>(prep))
{
assert(0 != pimpl_);
}
Rowset(Rowset const& other)
: pimpl_(other.pimpl_)
{
assert(0 != pimpl_);
pimpl_->incRef();
}
~Rowset()
{
assert(0 != pimpl_);
pimpl_->decRef();
}
Rowset& operator=(Rowset const& rhs)
{
assert(0 != pimpl_);
assert(0 != rhs.pimpl_);
rhs.incRef();
pimpl_->decRef();
pimpl_= rhs.pimpl_;
}
const_iterator begin() const
{
assert(0 != pimpl_);
return pimpl_->begin();
}
const_iterator end() const
{
assert(0 != pimpl_);
return pimpl_->end();
}
private:
// Pointer to implementation - the body
details::RowsetImpl<T>* pimpl_;
}; // class Rowset
} // namespace SOCI
#endif // SOCI_H_INCLUDED #endif // SOCI_H_INCLUDED
 End of changes. 3 change blocks. 
2204 lines changed or deleted 46 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/