soci-db2.h 8.63 KB
Newer Older
Denis Chapligin's avatar
Denis Chapligin committed
1
//
Mateusz Loskot's avatar
Mateusz Loskot committed
2
// Copyright (C) 2011-2013 Denis Chapligin
Denis Chapligin's avatar
Denis Chapligin committed
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//

#ifndef SOCI_DB2_H_INCLUDED
#define SOCI_DB2_H_INCLUDED

#ifdef _WIN32
# ifdef SOCI_DLL
#  ifdef SOCI_DB2_SOURCE
#   define SOCI_DB2_DECL __declspec(dllexport)
#  else
#   define SOCI_DB2_DECL __declspec(dllimport)
#  endif // SOCI_DB2_SOURCE
# endif // SOCI_DLL
#endif // _WIN32
//
// If SOCI_DB2_DECL isn't defined yet define it now
#ifndef SOCI_DB2_DECL
# define SOCI_DB2_DECL
#endif

27
#include <soci/soci-backend.h>
Denis Chapligin's avatar
Denis Chapligin committed
28 29 30

#include <cstddef>
#include <string>
Denis Chapligin's avatar
Denis Chapligin committed
31 32 33
#include <vector>
#include <iostream>
#include <sstream>
34
#include <string>
Denis Chapligin's avatar
Denis Chapligin committed
35
#include <cstring>
Denis Chapligin's avatar
Denis Chapligin committed
36 37 38 39 40

#include <sqlcli1.h>

namespace soci
{
41 42 43 44 45 46 47 48
    namespace details { namespace db2
    {
        enum binding_method
        {
            BOUND_BY_NONE,
            BOUND_BY_NAME,
            BOUND_BY_POSITION
        };
49 50 51 52 53 54 55 56 57 58 59

        inline SQLPOINTER int_as_ptr(int n)
        {
            union
            {
                SQLPOINTER p;
                int n;
            } u;
            u.n = n;
            return u.p;
        }
60 61 62
    }}

    static const std::size_t maxBuffer =  1024 * 1024 * 1024; //CLI limit is about 3 GB, but 1GB should be enough
Denis Chapligin's avatar
Denis Chapligin committed
63

64
class SOCI_DB2_DECL db2_soci_error : public soci_error {
Denis Chapligin's avatar
Denis Chapligin committed
65 66
public:
    db2_soci_error(std::string const & msg, SQLRETURN rc) : soci_error(msg),errorCode(rc) {};
67
    ~db2_soci_error() throw() SOCI_OVERRIDE { };
68 69

    //We have to extract error information before exception throwing, cause CLI handles could be broken at the construction time
Denis Chapligin's avatar
Denis Chapligin committed
70
    static const std::string sqlState(std::string const & msg,const SQLSMALLINT htype,const SQLHANDLE hndl);
71 72

    SQLRETURN errorCode;
Denis Chapligin's avatar
Denis Chapligin committed
73 74
};

75 76 77 78 79 80
// Option allowing to specify the "driver completion" parameter of
// SQLDriverConnect(). Its possible values are the same as the allowed values
// for this parameter in the official DB2 CLI, i.e. one of SQL_DRIVER_XXX
// (in string form as all options are strings currently).
extern SOCI_DB2_DECL char const * db2_option_driver_complete;

Denis Chapligin's avatar
Denis Chapligin committed
81 82 83 84 85
struct db2_statement_backend;

struct SOCI_DB2_DECL db2_standard_into_type_backend : details::standard_into_type_backend
{
    db2_standard_into_type_backend(db2_statement_backend &st)
Denis Chapligin's avatar
Denis Chapligin committed
86
        : statement_(st),buf(NULL)
Denis Chapligin's avatar
Denis Chapligin committed
87 88
    {}

89
    void define_by_pos(int& position, void* data, details::exchange_type type) SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
90

91 92
    void pre_fetch() SOCI_OVERRIDE;
    void post_fetch(bool gotData, bool calledFromFetch, indicator* ind) SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
93

94
    void clean_up() SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
95 96

    db2_statement_backend& statement_;
Denis Chapligin's avatar
Denis Chapligin committed
97 98 99 100 101 102 103

    char* buf;
    void *data;
    details::exchange_type type;
    int position;
    SQLSMALLINT cType;
    SQLLEN valueLen;
Denis Chapligin's avatar
Denis Chapligin committed
104 105 106 107 108
};

struct SOCI_DB2_DECL db2_vector_into_type_backend : details::vector_into_type_backend
{
    db2_vector_into_type_backend(db2_statement_backend &st)
Denis Chapligin's avatar
Denis Chapligin committed
109
        : statement_(st),buf(NULL)
Denis Chapligin's avatar
Denis Chapligin committed
110 111
    {}

112
    void define_by_pos(int& position, void* data, details::exchange_type type) SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
113

114 115
    void pre_fetch() SOCI_OVERRIDE;
    void post_fetch(bool gotData, indicator* ind) SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
116

117 118
    void resize(std::size_t sz) SOCI_OVERRIDE;
    std::size_t size() SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
119

120
    void clean_up() SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
121 122

    db2_statement_backend& statement_;
Denis Chapligin's avatar
Denis Chapligin committed
123 124 125 126 127 128 129

    void prepare_indicators(std::size_t size);

    SQLLEN *indptr;
    std::vector<SQLLEN> indVec;
    void *data;
    char *buf;
130
    int position_;
Denis Chapligin's avatar
Denis Chapligin committed
131 132 133
    details::exchange_type type;
    SQLSMALLINT cType;
    std::size_t colSize;
Denis Chapligin's avatar
Denis Chapligin committed
134 135 136 137 138
};

struct SOCI_DB2_DECL db2_standard_use_type_backend : details::standard_use_type_backend
{
    db2_standard_use_type_backend(db2_statement_backend &st)
139
        : statement_(st),buf(NULL),ind(0)
Denis Chapligin's avatar
Denis Chapligin committed
140 141
    {}

142 143
    void bind_by_pos(int& position, void* data, details::exchange_type type, bool readOnly) SOCI_OVERRIDE;
    void bind_by_name(std::string const& name, void* data, details::exchange_type type, bool readOnly) SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
144

145 146
    void pre_use(indicator const* ind) SOCI_OVERRIDE;
    void post_use(bool gotData, indicator* ind) SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
147

148
    void clean_up() SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
149 150

    db2_statement_backend& statement_;
Denis Chapligin's avatar
Denis Chapligin committed
151

152
    void *prepare_for_bind(void *data, SQLLEN &size, SQLSMALLINT &sqlType, SQLSMALLINT &cType);
Denis Chapligin's avatar
Denis Chapligin committed
153 154 155 156 157 158

    void *data;
    details::exchange_type type;
    int position;
    std::string name;
    char* buf;
159
    SQLLEN ind;
Denis Chapligin's avatar
Denis Chapligin committed
160 161 162 163 164
};

struct SOCI_DB2_DECL db2_vector_use_type_backend : details::vector_use_type_backend
{
    db2_vector_use_type_backend(db2_statement_backend &st)
Denis Chapligin's avatar
Denis Chapligin committed
165
        : statement_(st),buf(NULL) {}
Denis Chapligin's avatar
Denis Chapligin committed
166

167 168
    void bind_by_pos(int& position, void* data, details::exchange_type type) SOCI_OVERRIDE;
    void bind_by_name(std::string const& name, void* data, details::exchange_type type) SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
169

170
    void pre_use(indicator const* ind) SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
171

172
    std::size_t size() SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
173

174
    void clean_up() SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
175 176

    db2_statement_backend& statement_;
Denis Chapligin's avatar
Denis Chapligin committed
177 178 179 180 181 182 183 184 185 186 187

    void prepare_indicators(std::size_t size);
    void prepare_for_bind(void *&data, SQLUINTEGER &size,SQLSMALLINT &sqlType, SQLSMALLINT &cType);
    void bind_helper(int &position, void *data, details::exchange_type type);

    SQLLEN *indptr;
    std::vector<SQLLEN> indVec;
    void *data;
    char *buf;
    details::exchange_type type;
    std::size_t colSize;
Denis Chapligin's avatar
Denis Chapligin committed
188 189 190 191 192 193 194
};

struct db2_session_backend;
struct SOCI_DB2_DECL db2_statement_backend : details::statement_backend
{
    db2_statement_backend(db2_session_backend &session);

195 196 197
    void alloc() SOCI_OVERRIDE;
    void clean_up() SOCI_OVERRIDE;
    void prepare(std::string const& query, details::statement_type eType) SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
198

199 200
    exec_fetch_result execute(int number) SOCI_OVERRIDE;
    exec_fetch_result fetch(int number) SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
201

202 203 204
    long long get_affected_rows() SOCI_OVERRIDE;
    int get_number_of_rows() SOCI_OVERRIDE;
    std::string get_parameter_name(int index) const SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
205

206
    std::string rewrite_for_procedure_call(std::string const& query) SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
207

208 209
    int prepare_for_describe() SOCI_OVERRIDE;
    void describe_column(int colNum, data_type& dtype, std::string& columnName) SOCI_OVERRIDE;
210
    size_t column_size(int col);
Denis Chapligin's avatar
Denis Chapligin committed
211

212 213 214 215
    db2_standard_into_type_backend* make_into_type_backend() SOCI_OVERRIDE;
    db2_standard_use_type_backend* make_use_type_backend() SOCI_OVERRIDE;
    db2_vector_into_type_backend* make_vector_into_type_backend() SOCI_OVERRIDE;
    db2_vector_use_type_backend* make_vector_use_type_backend() SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
216 217

    db2_session_backend& session_;
Denis Chapligin's avatar
Denis Chapligin committed
218 219 220

    SQLHANDLE hStmt;
    std::string query_;
221
    std::vector<std::string> names_;
Denis Chapligin's avatar
Denis Chapligin committed
222 223
    bool hasVectorUseElements;
    SQLUINTEGER numRowsFetched;
224
    details::db2::binding_method use_binding_method_;
Denis Chapligin's avatar
Denis Chapligin committed
225 226 227 228 229 230
};

struct db2_rowid_backend : details::rowid_backend
{
    db2_rowid_backend(db2_session_backend &session);

231
    ~db2_rowid_backend() SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
232 233 234 235 236 237
};

struct db2_blob_backend : details::blob_backend
{
    db2_blob_backend(db2_session_backend& session);

238
    ~db2_blob_backend() SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
239

240 241 242 243 244
    std::size_t get_len() SOCI_OVERRIDE;
    std::size_t read(std::size_t offset, char* buf, std::size_t toRead) SOCI_OVERRIDE;
    std::size_t write(std::size_t offset, char const* buf, std::size_t toWrite) SOCI_OVERRIDE;
    std::size_t append(char const* buf, std::size_t toWrite) SOCI_OVERRIDE;
    void trim(std::size_t newLen) SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
245 246 247 248 249 250

    db2_session_backend& session_;
};

struct db2_session_backend : details::session_backend
{
251
    db2_session_backend(connection_parameters const& parameters);
Denis Chapligin's avatar
Denis Chapligin committed
252

253
    ~db2_session_backend() SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
254

255 256 257
    void begin() SOCI_OVERRIDE;
    void commit() SOCI_OVERRIDE;
    void rollback() SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
258

259
    std::string get_dummy_from_table() const SOCI_OVERRIDE { return "sysibm.sysdummy1"; }
260

261
    std::string get_backend_name() const SOCI_OVERRIDE { return "DB2"; }
Denis Chapligin's avatar
Denis Chapligin committed
262 263 264

    void clean_up();

265 266 267
    db2_statement_backend* make_statement_backend() SOCI_OVERRIDE;
    db2_rowid_backend* make_rowid_backend() SOCI_OVERRIDE;
    db2_blob_backend* make_blob_backend() SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
268

Denis Chapligin's avatar
Denis Chapligin committed
269 270 271
    void parseConnectString(std::string const &);
    void parseKeyVal(std::string const &);

272
    std::string connection_string_;
Denis Chapligin's avatar
Denis Chapligin committed
273
    bool autocommit;
274
    bool in_transaction;
Denis Chapligin's avatar
Denis Chapligin committed
275 276 277 278 279 280 281

    SQLHANDLE hEnv; /* Environment handle */
    SQLHANDLE hDbc; /* Connection handle */
};

struct SOCI_DB2_DECL db2_backend_factory : backend_factory
{
282
    db2_backend_factory() {}
283
    db2_session_backend* make_session(
284
        connection_parameters const & parameters) const SOCI_OVERRIDE;
Denis Chapligin's avatar
Denis Chapligin committed
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
};

extern SOCI_DB2_DECL db2_backend_factory const db2;

extern "C"
{

// for dynamic backend loading
SOCI_DB2_DECL backend_factory const* factory_db2();
SOCI_DB2_DECL void register_factory_db2();

} // extern "C"

} // namespace soci

#endif // SOCI_DB2_H_INCLUDED