| session.h | | session.h | |
| | | | |
| skipping to change at line 12 | | skipping to change at line 12 | |
| // Copyright (C) 2004-2008 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_SESSION_H_INCLUDED | | #ifndef SOCI_SESSION_H_INCLUDED | |
| #define SOCI_SESSION_H_INCLUDED | | #define SOCI_SESSION_H_INCLUDED | |
| | | | |
| #include "once-temp-type.h" | | #include "once-temp-type.h" | |
|
| | | #include "query_transformation.h" | |
| | | #include "connection-parameters.h" | |
| | | | |
| // std | | // std | |
| #include <cstddef> | | #include <cstddef> | |
| #include <ostream> | | #include <ostream> | |
| #include <sstream> | | #include <sstream> | |
| #include <string> | | #include <string> | |
| | | | |
| namespace soci | | namespace soci | |
| { | | { | |
| class values; | | class values; | |
|
| struct backend_factory; | | class backend_factory; | |
| | | | |
| namespace details | | namespace details | |
| { | | { | |
| | | | |
| class session_backend; | | class session_backend; | |
| class statement_backend; | | class statement_backend; | |
| class rowid_backend; | | class rowid_backend; | |
| class blob_backend; | | class blob_backend; | |
| | | | |
| } // namespace details | | } // namespace details | |
| | | | |
| class connection_pool; | | class connection_pool; | |
| | | | |
| class SOCI_DECL session | | class SOCI_DECL session | |
| { | | { | |
| public: | | public: | |
| session(); | | session(); | |
|
| | | explicit session(connection_parameters const & parameters); | |
| session(backend_factory const & factory, std::string const & connectStr
ing); | | session(backend_factory const & factory, std::string const & connectStr
ing); | |
| session(std::string const & backendName, std::string const & connectStr
ing); | | session(std::string const & backendName, std::string const & connectStr
ing); | |
| explicit session(std::string const & connectString); | | explicit session(std::string const & connectString); | |
| explicit session(connection_pool & pool); | | explicit session(connection_pool & pool); | |
| | | | |
| ~session(); | | ~session(); | |
| | | | |
|
| | | void open(connection_parameters const & parameters); | |
| void open(backend_factory const & factory, std::string const & connectS
tring); | | void open(backend_factory const & factory, std::string const & connectS
tring); | |
| void open(std::string const & backendName, std::string const & connectS
tring); | | void open(std::string const & backendName, std::string const & connectS
tring); | |
| void open(std::string const & connectString); | | void open(std::string const & connectString); | |
| void close(); | | void close(); | |
| void reconnect(); | | void reconnect(); | |
| | | | |
| void begin(); | | void begin(); | |
| void commit(); | | void commit(); | |
| void rollback(); | | void rollback(); | |
| | | | |
| // once and prepare are for syntax sugar only | | // once and prepare are for syntax sugar only | |
| details::once_type once; | | details::once_type once; | |
| details::prepare_type prepare; | | details::prepare_type prepare; | |
| | | | |
| // even more sugar | | // even more sugar | |
| template <typename T> | | template <typename T> | |
| details::once_temp_type operator<<(T const & t) { return once << t; } | | details::once_temp_type operator<<(T const & t) { return once << t; } | |
| | | | |
| std::ostringstream & get_query_stream(); | | std::ostringstream & get_query_stream(); | |
|
| | | std::string get_query() const; | |
| | | | |
| | | template <typename T> | |
| | | void set_query_transformation(T callback) | |
| | | { | |
| | | delete query_transformation_; | |
| | | query_transformation_= new details::query_transformation<T>(callbac | |
| | | k); | |
| | | } | |
| | | | |
| // support for basic logging | | // support for basic logging | |
| void set_log_stream(std::ostream * s); | | void set_log_stream(std::ostream * s); | |
| std::ostream * get_log_stream() const; | | std::ostream * get_log_stream() const; | |
| | | | |
| void log_query(std::string const & query); | | void log_query(std::string const & query); | |
| std::string get_last_query() const; | | std::string get_last_query() const; | |
| | | | |
| void set_got_data(bool gotData); | | void set_got_data(bool gotData); | |
| bool got_data() const; | | bool got_data() const; | |
| | | | |
| void uppercase_column_names(bool forceToUpper); | | void uppercase_column_names(bool forceToUpper); | |
| | | | |
| bool get_uppercase_column_names() const; | | 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 gi | |
| | | ven | |
| | | // sequence. Otherwise either the sequence is invalid (doesn't exist) o | |
| | | r | |
| | | // 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 va | |
| | | lue | |
| | | // 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 | | // for diagnostics and advanced users | |
| // (downcast it to expected back-end session class) | | // (downcast it to expected back-end session class) | |
| details::session_backend * get_backend() { return backEnd_; } | | details::session_backend * get_backend() { return backEnd_; } | |
| | | | |
| std::string get_backend_name() const; | | std::string get_backend_name() const; | |
| | | | |
| details::statement_backend * make_statement_backend(); | | details::statement_backend * make_statement_backend(); | |
| details::rowid_backend * make_rowid_backend(); | | details::rowid_backend * make_rowid_backend(); | |
| details::blob_backend * make_blob_backend(); | | details::blob_backend * make_blob_backend(); | |
| | | | |
| private: | | private: | |
| session(session const &); | | session(session const &); | |
| session& operator=(session const &); | | session& operator=(session const &); | |
| | | | |
| std::ostringstream query_stream_; | | std::ostringstream query_stream_; | |
|
| | | details::query_transformation_function* query_transformation_; | |
| | | | |
| std::ostream * logStream_; | | std::ostream * logStream_; | |
| std::string lastQuery_; | | std::string lastQuery_; | |
| | | | |
|
| backend_factory const * lastFactory_; | | connection_parameters lastConnectParameters_; | |
| std::string lastConnectString_; | | | |
| | | | |
| bool uppercaseColumnNames_; | | bool uppercaseColumnNames_; | |
| | | | |
| details::session_backend * backEnd_; | | details::session_backend * backEnd_; | |
| | | | |
| bool gotData_; | | bool gotData_; | |
| | | | |
| bool isFromPool_; | | bool isFromPool_; | |
| std::size_t poolPosition_; | | std::size_t poolPosition_; | |
| connection_pool * pool_; | | connection_pool * pool_; | |
| | | | |
End of changes. 8 change blocks. |
| 3 lines changed or deleted | | 36 lines changed or added | |
|
| soci-backend.h | | soci-backend.h | |
| | | | |
| skipping to change at line 24 | | skipping to change at line 24 | |
| #include <cstddef> | | #include <cstddef> | |
| #include <map> | | #include <map> | |
| #include <string> | | #include <string> | |
| | | | |
| namespace soci | | namespace soci | |
| { | | { | |
| | | | |
| // data types, as seen by the user | | // data types, as seen by the user | |
| enum data_type | | enum data_type | |
| { | | { | |
|
| dt_string, dt_date, dt_double, dt_integer, dt_unsigned_long, dt_long_lo
ng, dt_unsigned_long_long | | dt_string, dt_date, dt_double, dt_integer, dt_long_long, dt_unsigned_lo
ng_long | |
| }; | | }; | |
| | | | |
| // the enum type for indicator variables | | // the enum type for indicator variables | |
| enum indicator { i_ok, i_null, i_truncated }; | | enum indicator { i_ok, i_null, i_truncated }; | |
| | | | |
|
| | | class session; | |
| | | | |
| namespace details | | namespace details | |
| { | | { | |
| | | | |
| // data types, as used to describe exchange format | | // data types, as used to describe exchange format | |
| enum exchange_type | | enum exchange_type | |
| { | | { | |
|
| x_char, x_stdstring, | | x_char, | |
| x_short, x_integer, | | x_stdstring, | |
| x_unsigned_long, x_long_long, x_unsigned_long_long, | | x_short, | |
| x_double, x_stdtm, x_statement, | | x_integer, | |
| x_rowid, x_blob | | 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 statement_type | | enum statement_type | |
| { | | { | |
| st_one_time_query, | | st_one_time_query, | |
| st_repeatable_query | | st_repeatable_query | |
| }; | | }; | |
| | | | |
| // polymorphic into type backend | | // polymorphic into type backend | |
| | | | |
| skipping to change at line 224 | | skipping to change at line 232 | |
| class session_backend | | class session_backend | |
| { | | { | |
| public: | | public: | |
| session_backend() {} | | session_backend() {} | |
| virtual ~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; | |
| | | | |
|
| | | // At least one of these functions is usually not implemented for any g | |
| | | iven | |
| | | // backend as RDBMS support either sequences or auto-generated values, | |
| | | so | |
| | | // we don't declare them as pure virtuals to avoid having to define tri | |
| | | vial | |
| | | // versions of them in the derived classes. However every backend shoul | |
| | | d | |
| | | // define at least one of them to allow the code using auto-generated v | |
| | | alues | |
| | | // 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 std::string get_backend_name() const = 0; | |
| | | | |
| virtual statement_backend* make_statement_backend() = 0; | | virtual statement_backend* make_statement_backend() = 0; | |
| virtual rowid_backend* make_rowid_backend() = 0; | | virtual rowid_backend* make_rowid_backend() = 0; | |
| virtual blob_backend* make_blob_backend() = 0; | | virtual blob_backend* make_blob_backend() = 0; | |
| | | | |
| private: | | private: | |
| // noncopyable | | // noncopyable | |
| session_backend(session_backend const&); | | session_backend(session_backend const&); | |
| session_backend& operator=(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 backend_factory | | class connection_parameters; | |
| | | | |
| | | class SOCI_DECL backend_factory | |
| { | | { | |
|
| backend_factory() {} | | public: | |
| | | backend_factory() {} | |
| virtual ~backend_factory() {} | | virtual ~backend_factory() {} | |
| | | | |
| virtual details::session_backend* make_session( | | virtual details::session_backend* make_session( | |
|
| std::string const& connectString) const = 0; | | connection_parameters const& parameters) const = 0; | |
| }; | | }; | |
| | | | |
| } // namespace soci | | } // namespace soci | |
| | | | |
| #endif // SOCI_BACKEND_H_INCLUDED | | #endif // SOCI_BACKEND_H_INCLUDED | |
| | | | |
End of changes. 7 change blocks. |
| 9 lines changed or deleted | | 41 lines changed or added | |
|
| soci-odbc.h | | soci-odbc.h | |
| | | | |
| skipping to change at line 32 | | skipping to change at line 32 | |
| #ifndef SOCI_ODBC_DECL | | #ifndef SOCI_ODBC_DECL | |
| # define SOCI_ODBC_DECL | | # define SOCI_ODBC_DECL | |
| #endif | | #endif | |
| | | | |
| #include <vector> | | #include <vector> | |
| #include <soci-backend.h> | | #include <soci-backend.h> | |
| #if defined(_MSC_VER) || defined(__MINGW32__) | | #if defined(_MSC_VER) || defined(__MINGW32__) | |
| #include <windows.h> | | #include <windows.h> | |
| #endif | | #endif | |
| #include <sqlext.h> // ODBC | | #include <sqlext.h> // ODBC | |
|
| | | #include <string.h> // strcpy() | |
| | | | |
| namespace soci | | namespace soci | |
| { | | { | |
| | | | |
| // TODO: Do we want to make it a part of public interface? --mloskot | | // TODO: Do we want to make it a part of public interface? --mloskot | |
| namespace details | | namespace details | |
| { | | { | |
| std::size_t const odbc_max_buffer_length = 100 * 1024 * 1024; | | std::size_t const odbc_max_buffer_length = 100 * 1024 * 1024; | |
| } | | } | |
| | | | |
|
| | | // Option allowing to specify the "driver completion" parameter of | |
| | | // SQLDriverConnect(). Its possible values are the same as the allowed valu | |
| | | es | |
| | | // 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; | | struct odbc_statement_backend; | |
|
| struct odbc_standard_into_type_backend : details::standard_into_type_backen | | | |
| d | | // 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 defi | |
| | | nes | |
| | | // 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_; | |
| | | }; | |
| | | | |
| | | struct odbc_standard_into_type_backend : details::standard_into_type_backen | |
| | | d, | |
| | | private odbc_standard_type_backend | |
| | | _base | |
| { | | { | |
| odbc_standard_into_type_backend(odbc_statement_backend &st) | | odbc_standard_into_type_backend(odbc_statement_backend &st) | |
|
| : statement_(st), buf_(0) | | : odbc_standard_type_backend_base(st), buf_(0) | |
| {} | | {} | |
| | | | |
| virtual void define_by_pos(int &position, | | virtual void define_by_pos(int &position, | |
| void *data, details::exchange_type type); | | void *data, details::exchange_type type); | |
| | | | |
| virtual void pre_fetch(); | | virtual void pre_fetch(); | |
| virtual void post_fetch(bool gotData, bool calledFromFetch, | | virtual void post_fetch(bool gotData, bool calledFromFetch, | |
| indicator *ind); | | indicator *ind); | |
| | | | |
| virtual void clean_up(); | | virtual void clean_up(); | |
| | | | |
|
| odbc_statement_backend &statement_; | | | |
| char *buf_; // generic buffer | | char *buf_; // generic buffer | |
| void *data_; | | void *data_; | |
| details::exchange_type type_; | | details::exchange_type type_; | |
| int position_; | | int position_; | |
| SQLSMALLINT odbcType_; | | SQLSMALLINT odbcType_; | |
| SQLLEN valueLen_; | | SQLLEN valueLen_; | |
| }; | | }; | |
| | | | |
|
| struct odbc_vector_into_type_backend : details::vector_into_type_backend | | struct odbc_vector_into_type_backend : details::vector_into_type_backend, | |
| | | private odbc_standard_type_backend_b | |
| | | ase | |
| { | | { | |
| odbc_vector_into_type_backend(odbc_statement_backend &st) | | odbc_vector_into_type_backend(odbc_statement_backend &st) | |
|
| : statement_(st), indHolders_(NULL), | | : odbc_standard_type_backend_base(st), indHolders_(NULL), | |
| data_(NULL), buf_(NULL) {} | | data_(NULL), buf_(NULL) {} | |
| | | | |
| virtual void define_by_pos(int &position, | | virtual void define_by_pos(int &position, | |
| void *data, details::exchange_type type); | | void *data, details::exchange_type type); | |
| | | | |
| virtual void pre_fetch(); | | virtual void pre_fetch(); | |
| virtual void post_fetch(bool gotData, indicator *ind); | | virtual void post_fetch(bool gotData, indicator *ind); | |
| | | | |
| virtual void resize(std::size_t sz); | | virtual void resize(std::size_t sz); | |
| virtual std::size_t size(); | | virtual std::size_t size(); | |
| | | | |
| virtual void clean_up(); | | virtual void clean_up(); | |
| | | | |
| // helper function for preparing indicators | | // helper function for preparing indicators | |
| // (as part of the define_by_pos) | | // (as part of the define_by_pos) | |
| void prepare_indicators(std::size_t size); | | void prepare_indicators(std::size_t size); | |
| | | | |
|
| odbc_statement_backend &statement_; | | | |
| | | | |
| SQLLEN *indHolders_; | | SQLLEN *indHolders_; | |
| std::vector<SQLLEN> indHolderVec_; | | std::vector<SQLLEN> indHolderVec_; | |
| void *data_; | | void *data_; | |
| char *buf_; // generic buffer | | char *buf_; // generic buffer | |
| details::exchange_type type_; | | details::exchange_type type_; | |
| std::size_t colSize_; // size of the string column (used for strings
) | | std::size_t colSize_; // size of the string column (used for strings
) | |
| SQLSMALLINT odbcType_; | | SQLSMALLINT odbcType_; | |
| }; | | }; | |
| | | | |
|
| struct odbc_standard_use_type_backend : details::standard_use_type_backend | | 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_use_type_backend(odbc_statement_backend &st) | |
|
| : statement_(st), data_(0), buf_(0), indHolder_(0) {} | | : odbc_standard_type_backend_base(st), | |
| | | position_(-1), data_(0), buf_(0), indHolder_(0) {} | |
| void prepare_for_bind(void *&data, SQLLEN &size, | | | |
| SQLSMALLINT &sqlType, SQLSMALLINT &cType); | | | |
| void bind_helper(int &position, | | | |
| void *data, details::exchange_type type); | | | |
| | | | |
| virtual void bind_by_pos(int &position, | | virtual void bind_by_pos(int &position, | |
| void *data, details::exchange_type type, bool readOnly); | | void *data, details::exchange_type type, bool readOnly); | |
| virtual void bind_by_name(std::string const &name, | | virtual void bind_by_name(std::string const &name, | |
| void *data, details::exchange_type type, bool readOnly); | | void *data, details::exchange_type type, bool readOnly); | |
| | | | |
| virtual void pre_use(indicator const *ind); | | virtual void pre_use(indicator const *ind); | |
| virtual void post_use(bool gotData, indicator *ind); | | virtual void post_use(bool gotData, indicator *ind); | |
| | | | |
| virtual void clean_up(); | | virtual void clean_up(); | |
| | | | |
|
| odbc_statement_backend &statement_; | | // 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_; | | void *data_; | |
| details::exchange_type type_; | | details::exchange_type type_; | |
| char *buf_; | | char *buf_; | |
| SQLLEN indHolder_; | | SQLLEN indHolder_; | |
| }; | | }; | |
| | | | |
|
| struct odbc_vector_use_type_backend : details::vector_use_type_backend | | struct odbc_vector_use_type_backend : details::vector_use_type_backend, | |
| | | private odbc_standard_type_backend_ba | |
| | | se | |
| { | | { | |
| odbc_vector_use_type_backend(odbc_statement_backend &st) | | odbc_vector_use_type_backend(odbc_statement_backend &st) | |
|
| : statement_(st), indHolders_(NULL), | | : odbc_standard_type_backend_base(st), indHolders_(NULL), | |
| data_(NULL), buf_(NULL) {} | | data_(NULL), buf_(NULL) {} | |
| | | | |
| // helper function for preparing indicators | | // helper function for preparing indicators | |
| // (as part of the define_by_pos) | | // (as part of the define_by_pos) | |
| void prepare_indicators(std::size_t size); | | void prepare_indicators(std::size_t size); | |
| | | | |
| // common part for bind_by_pos and bind_by_name | | // common part for bind_by_pos and bind_by_name | |
| void prepare_for_bind(void *&data, SQLUINTEGER &size, SQLSMALLINT &sqlT
ype, SQLSMALLINT &cType); | | void prepare_for_bind(void *&data, SQLUINTEGER &size, SQLSMALLINT &sqlT
ype, SQLSMALLINT &cType); | |
| void bind_helper(int &position, | | void bind_helper(int &position, | |
| void *data, details::exchange_type type); | | void *data, details::exchange_type type); | |
| | | | |
| skipping to change at line 152 | | skipping to change at line 187 | |
| void *data, details::exchange_type type); | | void *data, details::exchange_type type); | |
| virtual void bind_by_name(std::string const &name, | | virtual void bind_by_name(std::string const &name, | |
| void *data, details::exchange_type type); | | void *data, details::exchange_type type); | |
| | | | |
| virtual void pre_use(indicator const *ind); | | virtual void pre_use(indicator const *ind); | |
| | | | |
| virtual std::size_t size(); | | virtual std::size_t size(); | |
| | | | |
| virtual void clean_up(); | | virtual void clean_up(); | |
| | | | |
|
| odbc_statement_backend &statement_; | | | |
| | | | |
| SQLLEN *indHolders_; | | SQLLEN *indHolders_; | |
| std::vector<SQLLEN> indHolderVec_; | | std::vector<SQLLEN> indHolderVec_; | |
| void *data_; | | void *data_; | |
| details::exchange_type type_; | | details::exchange_type type_; | |
| char *buf_; // generic buffer | | char *buf_; // generic buffer | |
| std::size_t colSize_; // size of the string column (used for strings
) | | std::size_t colSize_; // size of the string column (used for strings
) | |
| // used for strings only | | // used for strings only | |
| std::size_t maxSize_; | | std::size_t maxSize_; | |
| }; | | }; | |
| | | | |
| | | | |
| skipping to change at line 200 | | skipping to change at line 233 | |
| virtual odbc_standard_use_type_backend * make_use_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_into_type_backend * make_vector_into_type_backend()
; | |
| virtual odbc_vector_use_type_backend * make_vector_use_type_backend(); | | virtual odbc_vector_use_type_backend * make_vector_use_type_backend(); | |
| | | | |
| odbc_session_backend &session_; | | odbc_session_backend &session_; | |
| SQLHSTMT hstmt_; | | SQLHSTMT hstmt_; | |
| SQLUINTEGER numRowsFetched_; | | SQLUINTEGER numRowsFetched_; | |
| bool hasVectorUseElements_; | | bool hasVectorUseElements_; | |
| bool boundByName_; | | bool boundByName_; | |
| bool boundByPos_; | | bool boundByPos_; | |
|
| | | bool lastNoData_; // true if last query returned SQL_NO_DATA | |
| | | | |
| std::string query_; | | std::string query_; | |
| std::vector<std::string> names_; // list of names for named binds | | std::vector<std::string> names_; // list of names for named binds | |
| | | | |
| }; | | }; | |
| | | | |
| struct odbc_rowid_backend : details::rowid_backend | | struct odbc_rowid_backend : details::rowid_backend | |
| { | | { | |
| odbc_rowid_backend(odbc_session_backend &session); | | odbc_rowid_backend(odbc_session_backend &session); | |
| | | | |
| | | | |
| skipping to change at line 232 | | skipping to change at line 266 | |
| 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); | | std::size_t toWrite); | |
| virtual std::size_t append(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); | | virtual void trim(std::size_t newLen); | |
| | | | |
| odbc_session_backend &session_; | | odbc_session_backend &session_; | |
| }; | | }; | |
| | | | |
| struct odbc_session_backend : details::session_backend | | struct odbc_session_backend : details::session_backend | |
| { | | { | |
|
| odbc_session_backend(std::string const &connectString); | | odbc_session_backend(connection_parameters const & parameters); | |
| | | | |
| ~odbc_session_backend(); | | ~odbc_session_backend(); | |
| | | | |
| virtual void begin(); | | virtual void begin(); | |
| virtual void commit(); | | virtual void commit(); | |
| virtual void rollback(); | | 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"; } | | virtual std::string get_backend_name() const { return "odbc"; } | |
| | | | |
| void reset_transaction(); | | void reset_transaction(); | |
| | | | |
| void clean_up(); | | void clean_up(); | |
| | | | |
| virtual odbc_statement_backend * make_statement_backend(); | | virtual odbc_statement_backend * make_statement_backend(); | |
| virtual odbc_rowid_backend * make_rowid_backend(); | | virtual odbc_rowid_backend * make_rowid_backend(); | |
| virtual odbc_blob_backend * make_blob_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_; | | SQLHENV henv_; | |
| SQLHDBC hdbc_; | | SQLHDBC hdbc_; | |
|
| | | | |
| | | std::string connection_string_; | |
| | | database_product product_; | |
| }; | | }; | |
| | | | |
| class SOCI_ODBC_DECL odbc_soci_error : public soci_error | | class SOCI_ODBC_DECL odbc_soci_error : public soci_error | |
| { | | { | |
| SQLCHAR message_[SQL_MAX_MESSAGE_LENGTH + 1]; | | SQLCHAR message_[SQL_MAX_MESSAGE_LENGTH + 1]; | |
| SQLCHAR sqlstate_[SQL_SQLSTATE_SIZE + 1]; | | SQLCHAR sqlstate_[SQL_SQLSTATE_SIZE + 1]; | |
| SQLINTEGER sqlcode_; | | SQLINTEGER sqlcode_; | |
| | | | |
| public: | | public: | |
| odbc_soci_error(SQLSMALLINT htype, | | odbc_soci_error(SQLSMALLINT htype, | |
| SQLHANDLE hndl, | | SQLHANDLE hndl, | |
| std::string const & msg) | | std::string const & msg) | |
| : soci_error(msg) | | : soci_error(msg) | |
| { | | { | |
|
| | | const char* socierror = NULL; | |
| | | | |
| SQLSMALLINT length, i = 1; | | SQLSMALLINT length, i = 1; | |
|
| SQLGetDiagRec(htype, hndl, i, sqlstate_, &sqlcode_, | | switch ( SQLGetDiagRec(htype, hndl, i, sqlstate_, &sqlcode_, | |
| message_, SQL_MAX_MESSAGE_LENGTH + 1, | | message_, SQL_MAX_MESSAGE_LENGTH + 1, | |
| &length); | | &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 (length == 0) | | if (socierror) | |
| { | | { | |
|
| message_[0] = 0; | | // 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; | | sqlcode_ = 0; | |
| } | | } | |
| } | | } | |
| | | | |
| SQLCHAR const * odbc_error_code() const | | SQLCHAR const * odbc_error_code() const | |
| { | | { | |
| return reinterpret_cast<SQLCHAR const *>(sqlstate_); | | return reinterpret_cast<SQLCHAR const *>(sqlstate_); | |
| } | | } | |
| SQLINTEGER native_error_code() const | | SQLINTEGER native_error_code() const | |
| { | | { | |
| | | | |
| skipping to change at line 304 | | skipping to change at line 396 | |
| if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DA
TA) | | if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DA
TA) | |
| { | | { | |
| return true; | | return true; | |
| } | | } | |
| else | | else | |
| { | | { | |
| return false; | | 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 | | struct odbc_backend_factory : backend_factory | |
| { | | { | |
|
| odbc_backend_factory() {} | | odbc_backend_factory() {} | |
| virtual odbc_session_backend * make_session( | | virtual odbc_session_backend * make_session( | |
|
| std::string const &connectString) const; | | connection_parameters const & parameters) const; | |
| }; | | }; | |
| | | | |
| extern SOCI_ODBC_DECL odbc_backend_factory const odbc; | | extern SOCI_ODBC_DECL odbc_backend_factory const odbc; | |
| | | | |
| extern "C" | | extern "C" | |
| { | | { | |
| | | | |
| // for dynamic backend loading | | // for dynamic backend loading | |
| SOCI_ODBC_DECL backend_factory const * factory_odbc(); | | SOCI_ODBC_DECL backend_factory const * factory_odbc(); | |
| SOCI_ODBC_DECL void register_factory_odbc(); | | SOCI_ODBC_DECL void register_factory_odbc(); | |
| | | | |
End of changes. 26 change blocks. |
| 28 lines changed or deleted | | 141 lines changed or added | |
|
| soci-postgresql.h | | soci-postgresql.h | |
| | | | |
| skipping to change at line 147 | | skipping to change at line 147 | |
| details::exchange_type type_; | | details::exchange_type type_; | |
| int position_; | | int position_; | |
| std::string name_; | | std::string name_; | |
| std::vector<char *> buffers_; | | std::vector<char *> buffers_; | |
| }; | | }; | |
| | | | |
| struct postgresql_session_backend; | | struct postgresql_session_backend; | |
| struct postgresql_statement_backend : details::statement_backend | | struct postgresql_statement_backend : details::statement_backend | |
| { | | { | |
| postgresql_statement_backend(postgresql_session_backend & session); | | postgresql_statement_backend(postgresql_session_backend & session); | |
|
| | | ~postgresql_statement_backend(); | |
| | | | |
| virtual void alloc(); | | virtual void alloc(); | |
| virtual void clean_up(); | | virtual void clean_up(); | |
| virtual void prepare(std::string const & query, | | virtual void prepare(std::string const & query, | |
| details::statement_type stType); | | details::statement_type stType); | |
| | | | |
| virtual exec_fetch_result execute(int number); | | virtual exec_fetch_result execute(int number); | |
| virtual exec_fetch_result fetch(int number); | | virtual exec_fetch_result fetch(int number); | |
| | | | |
| virtual long long get_affected_rows(); | | virtual long long get_affected_rows(); | |
| | | | |
| skipping to change at line 231 | | skipping to change at line 232 | |
| virtual void trim(std::size_t newLen); | | virtual void trim(std::size_t newLen); | |
| | | | |
| postgresql_session_backend & session_; | | postgresql_session_backend & session_; | |
| | | | |
| unsigned long oid_; // oid of the large object | | unsigned long oid_; // oid of the large object | |
| int fd_; // descriptor of the large object | | int fd_; // descriptor of the large object | |
| }; | | }; | |
| | | | |
| struct postgresql_session_backend : details::session_backend | | struct postgresql_session_backend : details::session_backend | |
| { | | { | |
|
| postgresql_session_backend(std::string const & connectString); | | postgresql_session_backend(connection_parameters const & parameters); | |
| | | | |
| ~postgresql_session_backend(); | | ~postgresql_session_backend(); | |
| | | | |
| virtual void begin(); | | virtual void begin(); | |
| virtual void commit(); | | virtual void commit(); | |
| virtual void rollback(); | | virtual void rollback(); | |
| | | | |
|
| | | void deallocate_prepared_statement(const std::string & statementName); | |
| | | | |
| virtual std::string get_backend_name() const { return "postgresql"; } | | virtual std::string get_backend_name() const { return "postgresql"; } | |
| | | | |
| void clean_up(); | | void clean_up(); | |
| | | | |
| virtual postgresql_statement_backend * make_statement_backend(); | | virtual postgresql_statement_backend * make_statement_backend(); | |
| virtual postgresql_rowid_backend * make_rowid_backend(); | | virtual postgresql_rowid_backend * make_rowid_backend(); | |
| virtual postgresql_blob_backend * make_blob_backend(); | | virtual postgresql_blob_backend * make_blob_backend(); | |
| | | | |
| std::string get_next_statement_name(); | | std::string get_next_statement_name(); | |
| | | | |
| int statementCount_; | | int statementCount_; | |
| PGconn * conn_; | | PGconn * conn_; | |
| }; | | }; | |
| | | | |
| struct postgresql_backend_factory : backend_factory | | struct postgresql_backend_factory : backend_factory | |
| { | | { | |
|
| postgresql_backend_factory() {} | | postgresql_backend_factory() {} | |
| virtual postgresql_session_backend * make_session( | | virtual postgresql_session_backend * make_session( | |
|
| std::string const & connectString) const; | | connection_parameters const & parameters) const; | |
| }; | | }; | |
| | | | |
| extern SOCI_POSTGRESQL_DECL postgresql_backend_factory const postgresql; | | extern SOCI_POSTGRESQL_DECL postgresql_backend_factory const postgresql; | |
| | | | |
| extern "C" | | extern "C" | |
| { | | { | |
| | | | |
| // for dynamic backend loading | | // for dynamic backend loading | |
| SOCI_POSTGRESQL_DECL backend_factory const * factory_postgresql(); | | SOCI_POSTGRESQL_DECL backend_factory const * factory_postgresql(); | |
| SOCI_POSTGRESQL_DECL void register_factory_postgresql(); | | SOCI_POSTGRESQL_DECL void register_factory_postgresql(); | |
| | | | |
End of changes. 5 change blocks. |
| 3 lines changed or deleted | | 6 lines changed or added | |
|