Project

General

Profile

Bug #9055 ยป wt.db2.diff

Torsten Schulz, 09/09/2021 04:43 PM

View differences:

wt-4.5.0-patched/CMakeLists.txt 2021-04-20 16:48:29.573236713 +0200
38 38
OPTION(ENABLE_FIREBIRD "Build FirebirdSQL backend for Wt::Dbo" ON)
39 39
OPTION(ENABLE_MYSQL "Build mariadb/mysql backend for Wt::Dbo" ON)
40 40
OPTION(ENABLE_MSSQLSERVER "Build Microsoft SQL Server backend for Wt::Dbo" ON)
41
OPTION(ENABLE_DB2 "Build DB2 backend for Wt::DBO" ON)
41 42
OPTION(ENABLE_QT4 "Build Qt4 interworking library (libwtwithqt)" ON)
42 43
OPTION(ENABLE_QT5 "Build Qt5 interworking library (libwtwithqt5)" ON)
43 44
OPTION(ENABLE_LIBWTTEST "Build Wt::Test" ON)
wt-4.5.0-patched/src/Wt/Auth/Dbo/UserDatabase.h 2021-04-20 16:48:27.409255910 +0200
100 100
	  session_.query<Wt::Dbo::ptr<DboType> >(std::string() +
101 101
	       "select u from " + session_.tableNameQuoted<DboType>() + " u "
102 102
	       "join " + session_.tableNameQuoted<AuthIdentityType>() + " i "
103
	       "on u.id = i.\"" + session_.tableName<DboType>() + "_id\"")
103
           "on u.\"id\" = i.\"" + session_.tableName<DboType>() + "_id\"")
104 104
	      .where("i.\"provider\" = ?").bind(provider);
105 105
      if (authService_ && authService_->identityPolicy() == IdentityPolicy::EmailAddress) {
106 106
	query.where("lower(i.\"identity\") = lower(?)").bind(identity);
......
359 360
	    (std::string() +
360 361
	     "select u from " + session_.tableNameQuoted<DboType>() + " u "
361 362
	     "join " + session_.tableNameQuoted<AuthTokenType>() + " t "
362
	     "on u.id = t.\"" + session_.tableName<DboType>() + "_id\"")
363
	     "on u.\"id\" = t.\"" + session_.tableName<DboType>() + "_id\"")
363 364
	    .where("t.\"value\" = ?").bind(hash)
364 365
	    .where("t.\"expires\" > ?").bind(WDateTime::currentDateTime()));
365 366
    t.commit();
wt-4.5.0-patched/src/Wt/Dbo/backend/CMakeLists.txt 2021-04-20 16:48:27.289256974 +0200
398 400
  MESSAGE("** Wt::Dbo: not building Microsoft SQL Server backend.")
399 401
  SET(HAVE_MSSQLSERVER OFF CACHE INTERNAL "building Microsoft SQL Server backend" FORCE)
400 402
ENDIF(ENABLE_MSSQLSERVER AND ODBC_FOUND)
403

  
404

  
405

  
406

  
407
IF(ENABLE_DB2 AND ODBC_FOUND)
408

  
409
  SET(HAVE_DB2 ON CACHE INTERNAL "building DB2 backend" FORCE)
410

  
411
  MESSAGE("** Wt::Dbo: building DB2 backend.")
412

  
413
  IF(WIN32)
414
    IF(SHARED_LIBS)
415
      CONFIGURE_FILE(wtdbodb2-version.rc.in
416
                     ${CMAKE_CURRENT_BINARY_DIR}/wtdbodb2-version.rc)
417
      SET(db2_SRCS ${db2_SRCS}
418
          ${CMAKE_CURRENT_BINARY_DIR}/wtdbodb2-version.rc)
419
    ENDIF(SHARED_LIBS)
420
  ENDIF(WIN32)
421

  
422
  ADD_LIBRARY(wtdbodb2
423
    DB2.h DB2.C
424
    ${db2_SRCS}
425
  )
426

  
427
  SET_PROPERTY(TARGET wtdbodb2 PROPERTY C_VISIBILITY_PRESET hidden)
428
  SET_PROPERTY(TARGET wtdbodb2 PROPERTY CXX_VISIBILITY_PRESET hidden)
429
  SET_PROPERTY(TARGET wtdbodb2 PROPERTY VISIBILITY_INLINES_HIDDEN YES)
430

  
431
  TARGET_LINK_LIBRARIES(wtdbodb2
432
    PUBLIC
433
      wtdbo
434
    PRIVATE
435
      ${ODBC_LIBRARIES}
436
  )
437

  
438
  INCLUDE_DIRECTORIES(${ODBC_INCLUDE})
439

  
440
  INSTALL(TARGETS wtdbodb2
441
    EXPORT wt-target-wtdbodb2
442
    RUNTIME DESTINATION bin
443
    LIBRARY DESTINATION ${LIB_INSTALL_DIR}
444
    ARCHIVE DESTINATION ${LIB_INSTALL_DIR})
445

  
446
  INSTALL(EXPORT wt-target-wtdbodb2
447
          DESTINATION ${CMAKE_INSTALL_DIR}/wt
448
          NAMESPACE Wt::)
449

  
450
  SET_TARGET_PROPERTIES(
451
    wtdbodb2
452
  PROPERTIES
453
    EXPORT_NAME DboDB2
454
    VERSION ${VERSION_SERIES}.${VERSION_MAJOR}.${VERSION_MINOR}
455
    DEBUG_POSTFIX ${DEBUG_LIB_POSTFIX}
456
    )
457

  
458
  IF(MSVC)
459
    SET_TARGET_PROPERTIES(
460
      wtdbodb2
461
    PROPERTIES
462
      COMPILE_FLAGS "${BUILD_PARALLEL} /wd4251 /wd4275 /wd4267"
463
    )
464
    SET_TARGET_PROPERTIES(wtdbodb2 PROPERTIES FOLDER "dbo")
465
  endif(MSVC)
466

  
467
  INSTALL_FILES(/include/Wt/Dbo/backend "^.*DB2.*h$")
468
ELSE(ENABLE_DB2 AND ODBC_FOUND)
469
  MESSAGE("** Wt::Dbo: not building DB2 backend.")
470
  IF(ENABLE_DB2)
471
    MESSAGE("     ODBC not found")
472
  ENDIF(ENABLE_DB2)
473
  SET(HAVE_DB2 OFF CACHE INTERNAL "building DB2 backend" FORCE)
474
ENDIF(ENABLE_DB2 AND ODBC_FOUND)
wt-4.5.0-patched/src/Wt/Dbo/backend/DB2.C 2021-04-20 16:48:27.289256974 +0200
1
/*
2
 * Copyright (C) 2017 Emweb bv, Herent, Belgium.
3
 *
4
 * See the LICENSE file for terms of use.
5
 */
6
#include "Wt/Dbo/backend/DB2.h"
7

  
8
#include "Wt/Dbo/Exception.h"
9
#include "Wt/Dbo/Logger.h"
10
#include "Wt/Dbo/StringStream.h"
11

  
12
#include "Wt/Date/date.h"
13

  
14
#ifdef WT_WIN32
15
#define NOMINMAX
16
#include <windows.h>
17
#endif // WT_WIN32
18
#include <sql.h>
19
#include <sqlext.h>
20
#ifndef WT_WIN32
21
#include <sqlucode.h>
22

  
23
#include <codecvt>
24
#include <string>
25
#endif // WT_WIN32
26

  
27
#include <cstring>
28
#include <iostream>
29
#include <vector>
30

  
31
// define from sqlncli.h
32
// See: https://docs.microsoft.com/en-us/sql/relational-databases/native-client/features/using-multiple-active-result-sets-mars
33
#ifndef SQL_COPT_SS_MARS_ENABLED
34
#define SQL_COPT_SS_MARS_ENABLED 1224
35
#define SQL_MARS_ENABLED_YES 1L
36
#endif
37

  
38
namespace Wt {
39
  namespace Dbo {
40

  
41
LOGGER("Dbo.backend.DB2Server");
42

  
43
    namespace backend {
44

  
45
class DB2ServerException : public Exception
46
{
47
public:
48
  DB2ServerException(const std::string& msg,
49
                       const std::string &sqlState = std::string())
50
   : Exception(msg, sqlState)
51
  { }
52
};
53

  
54
namespace {
55

  
56
static void handleErr(SQLSMALLINT handleType, SQLHANDLE handle, SQLRETURN rc)
57
{
58
  if (SQL_SUCCEEDED(rc))
59
    return;
60

  
61
  SQLCHAR sqlState[6];
62
  SQLINTEGER nativeErr = 0;
63
  SQLSMALLINT msgLength = 0;
64
  SQLCHAR buf[SQL_MAX_MESSAGE_LENGTH];
65
  SQLGetDiagRec(
66
    handleType,
67
    handle,
68
    1,
69
    sqlState,
70
    &nativeErr,
71
    buf,
72
    sizeof(buf),
73
    &msgLength
74
  );
75
  throw DB2ServerException(
76
          std::string((const char*)buf, msgLength),
77
          std::string((const char*)sqlState, 5));
78
}
79

  
80
#ifndef WT_WIN32
81
std::u16string toUTF16(const std::string &str)
82
{
83
  return
84
    std::wstring_convert<
85
      std::codecvt_utf8_utf16<char16_t>, char16_t>{}.from_bytes(str.data());
86
}
87
#endif // WT_WIN32
88

  
89
#ifdef WT_WIN32
90
typedef std::basic_string<SQLWCHAR> ConnectionStringType;
91
#else // WT_WIN32
92
typedef std::u16string ConnectionStringType;
93
#endif // WT_WIN32
94

  
95
}
96

  
97
struct DB2::Impl {
98
  Impl(const ConnectionStringType &str)
99
    : env(NULL),
100
      dbc(NULL),
101
      stmt(NULL),
102
      connectionString(str)
103
  {
104
    resultBuffer.buf = (char*)malloc(256);
105
    resultBuffer.size = 256;
106
  }
107

  
108
  Impl(const Impl &other)
109
    : env(NULL),
110
      dbc(NULL),
111
      stmt(NULL),
112
      connectionString(other.connectionString)
113
  {
114
    resultBuffer.buf = (char*)malloc(256);
115
    resultBuffer.size = 256;
116
  }
117

  
118
  ~Impl()
119
  {
120
    free(resultBuffer.buf);
121
    if (stmt)
122
      SQLFreeHandle(SQL_HANDLE_STMT, stmt);
123
    if (dbc) {
124
      SQLDisconnect(dbc);
125
      SQLFreeHandle(SQL_HANDLE_DBC, dbc);
126
    }
127
    if (env)
128
      SQLFreeHandle(SQL_HANDLE_ENV, env);
129
  }
130

  
131
  void connect()
132
  {
133
    // Create SQL env handle
134
    SQLRETURN res = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
135
    if (res == SQL_ERROR)
136
      throw DB2ServerException("Failed to allocate ODBC environment handle!");
137
    // Set ODBC version to 3
138
    res = SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);
139
    handleErr(SQL_HANDLE_ENV, env, res);
140
    // Create SQL connection handle
141
    res = SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
142
    handleErr(SQL_HANDLE_ENV, env, res);
143
    // Turn off autocommit
144
    res = SQLSetConnectAttrW(dbc, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF, SQL_IS_UINTEGER);
145
    handleErr(SQL_HANDLE_DBC, dbc, res);
146
    // Turn on MARS (Multiple Active Result Sets)
147
//    res = SQLSetConnectAttrW(dbc, SQL_COPT_SS_MARS_ENABLED, (SQLPOINTER)SQL_MARS_ENABLED_YES, SQL_IS_UINTEGER);
148
    handleErr(SQL_HANDLE_DBC, dbc, res);
149
    // Connect
150
    res = SQLDriverConnectW(
151
      dbc,
152
      NULL,
153
      (SQLWCHAR*)&(connectionString)[0],
154
      connectionString.size(),
155
      NULL,
156
      0,
157
      NULL,
158
      SQL_DRIVER_NOPROMPT);
159
    handleErr(SQL_HANDLE_DBC, dbc, res);
160
  }
161

  
162
  SQLHENV env; // Environment handle
163
  SQLHDBC dbc; // Connection handle
164
  SQLHSTMT stmt; // Statement handle for executeSql
165
  ConnectionStringType connectionString;
166
  struct ResultBuffer {
167
    char *buf;
168
    std::size_t size;
169
  } resultBuffer;
170
};
171

  
172
class DB2ServerStatement : public SqlStatement {
173
public:
174
  DB2ServerStatement(DB2 &conn, const std::string &sql)
175
    : paramValues_(NULL),
176
      parameterCount_(0),
177
      resultColCount_(0),
178
      stmt_(NULL),
179
      conn_(conn),
180
      sql_(sql),
181
      affectedRows_(0),
182
      lastId_(-1)
183
  {
184
    SQLRETURN rc = SQLAllocHandle(SQL_HANDLE_STMT, conn.impl_->dbc, &stmt_);
185
    handleErr(SQL_HANDLE_DBC, conn.impl_->dbc, rc);
186
#ifdef WT_WIN32
187
    if (sql.empty()) {
188
      // Empty query, should be an error, but we'll leave the reporting
189
      // of that error to ODBC
190
      SQLWCHAR wstr[] = L"";
191
      rc = SQLPrepareW(stmt_, wstr, 0);
192
    } else {
193
      int wstrlen = MultiByteToWideChar(CP_UTF8, 0, &sql[0], sql.size(), NULL, 0);
194
      assert(wstrlen != 0);
195
      SQLWCHAR *wstr = new SQLWCHAR[wstrlen + 1];
196
      wstrlen = MultiByteToWideChar(CP_UTF8, 0, &sql[0], sql.size(), wstr, wstrlen);
197
      assert(wstrlen != 0);
198
      wstr[wstrlen] = 0;
199
      rc = SQLPrepareW(stmt_, wstr, wstrlen);
200
      delete[] wstr;
201
    }
202
#else // WT_WIN32
203
    std::u16string wstr = toUTF16(sql);
204
    rc = SQLPrepareW(stmt_, (SQLWCHAR*)&wstr[0], wstr.size());
205
#endif // WT_WIN32
206
    handleErr(SQL_HANDLE_STMT, stmt_, rc);
207
    rc = SQLNumParams(stmt_, &parameterCount_);
208
    handleErr(SQL_HANDLE_STMT, stmt_, rc);
209
    SQLSMALLINT numCols = 0;
210
    rc = SQLNumResultCols(stmt_, &numCols);
211
    handleErr(SQL_HANDLE_STMT, stmt_, rc);
212
    resultColCount_ = numCols;
213
    if (parameterCount_ > 0) {
214
      paramValues_ = new Value[parameterCount_];
215
      std::memset(paramValues_, 0, parameterCount_ * sizeof(Value));
216
    }
217
  }
218

  
219
  virtual ~DB2ServerStatement()
220
  {
221
    if (stmt_) {
222
      SQLFreeStmt(stmt_, SQL_CLOSE);
223
      SQLFreeHandle(SQL_HANDLE_STMT, stmt_);
224
    }
225
    for (SQLSMALLINT i = 0; i < parameterCount_; ++i)
226
      paramValues_[i].clear();
227
    delete[] paramValues_;
228
  }
229

  
230

  
231
  virtual void reset() override
232
  {
233
    SQLFreeStmt(stmt_, SQL_CLOSE);
234
  }
235

  
236
  virtual void bind(int column, const std::string &value) override
237
  {
238
    checkColumnIndex(column);
239
    Value &v = paramValues_[column];
240
    bool newPtr = true;
241
    if (value.empty()) {
242
      newPtr = createOrResizeBuffer(v, 0);
243
      v.lengthOrInd = 0;
244
    } else {
245
#ifdef WT_WIN32
246
      // Convert value from UTF-8 to WCHAR (UTF-16)
247
      // Measure length required
248
      int bufsize = MultiByteToWideChar(CP_UTF8, 0, value.c_str(), value.size(), NULL, 0);
249
      assert(bufsize != 0);
250
      newPtr = createOrResizeBuffer(v, (bufsize + 1) * sizeof(WCHAR));
251
      bufsize = MultiByteToWideChar(CP_UTF8, 0, value.c_str(), value.size(), (WCHAR*)v.v.buf.p, bufsize);
252
      assert(bufsize != 0);
253
      ((WCHAR*)v.v.buf.p)[bufsize] = 0;
254
      v.lengthOrInd = bufsize * sizeof(WCHAR);
255
#else // WT_WIN32
256
      newPtr = createOrResizeBuffer(v, value.size() + 1);
257
      memcpy(v.v.buf.p, value.c_str(), value.size() + 1);
258
      v.lengthOrInd = value.size();
259
#endif // WT_WIN32
260
    }
261
    if (newPtr || v.type != SQL_C_WCHAR) {
262
      v.type = SQL_C_WCHAR;
263
      SQLRETURN rc = SQLBindParameter(
264
        /*StatementHandle: */stmt_,
265
        /*ParameterNumber: */column + 1,
266
        /*InputOutputType: */SQL_PARAM_INPUT,
267
#ifdef WT_WIN32
268
        /*ValueType: */SQL_C_WCHAR,
269
#else // WT_WIN32
270
        /*ValueType: */SQL_C_CHAR, // UTF-8 to UTF-16 done by SQL Server driver
271
#endif // WT_WIN32
272
        /*ParameterType: */SQL_WVARCHAR,
273
        /*ColumnSize: */0, // Ignored
274
        /*DecimalDigits: */0, // ignored
275
        /*ParameterValuePtr: */v.v.buf.p,
276
        /*BufferLength: */v.v.buf.size,
277
        /*StrLen_or_IndPtr: */&v.lengthOrInd
278
      );
279
      handleErr(SQL_HANDLE_STMT, stmt_, rc);
280
    }
281
  }
282

  
283
  virtual void bind(int column, short value) override
284
  {
285
    checkColumnIndex(column);
286
    Value &v = paramValues_[column];
287
    if (v.type == SQL_C_SSHORT) {
288
      v.v.s = value;
289
      v.lengthOrInd = 0;
290
    } else {
291
      v.clear();
292
      v.v.s = value;
293
      v.type = SQL_C_SSHORT;
294
      SQLRETURN rc = SQLBindParameter(
295
        /*StatementHandle: */stmt_,
296
        /*ParameterNumber: */column + 1,
297
        /*InputOutputType: */SQL_PARAM_INPUT,
298
        /*ValueType: */SQL_C_SSHORT,
299
        /*ParameterType: */SQL_INTEGER,
300
        /*ColumnSize: */0, // ignored
301
        /*DecimalDigits: */0, // ignored
302
        /*ParameterValuePtr: */&v.v.s,
303
        /*BufferLength: */0,
304
        /*StrLen_or_IndPtr: */&v.lengthOrInd
305
      );
306
      handleErr(SQL_HANDLE_STMT, stmt_, rc);
307
    }
308
  }
309

  
310
  virtual void bind(int column, int value) override
311
  {
312
    checkColumnIndex(column);
313
    Value &v = paramValues_[column];
314
    if (v.type == SQL_C_SLONG) {
315
      v.v.i = value;
316
      v.lengthOrInd = 0;
317
    } else {
318
      v.clear();
319
      v.v.i = value;
320
      v.type = SQL_C_SLONG;
321
      SQLRETURN rc = SQLBindParameter(
322
        /*StatementHandle: */stmt_,
323
        /*ParameterNumber: */column + 1,
324
        /*InputOutputType: */SQL_PARAM_INPUT,
325
        /*ValueType: */SQL_C_SLONG,
326
        /*ParameterType: */SQL_INTEGER,
327
        /*Columnsize: */0, // seems ignored?
328
        /*DecimalDigits: */0, // ignored
329
        /*ParameterValuePtr: */&v.v.i,
330
        /*BufferLength: */0,
331
        /*StrLen_or_IndPtr: */&v.lengthOrInd
332
      );
333
      handleErr(SQL_HANDLE_STMT, stmt_, rc);
334
    }
335
  }
336

  
337
  virtual void bind(int column, long long value) override
338
  {
339
    checkColumnIndex(column);
340
    Value &v = paramValues_[column];
341
    if (v.type == SQL_C_SBIGINT) {
342
      v.v.ll = value;
343
      v.lengthOrInd = 0;
344
    } else {
345
      v.clear();
346
      v.v.ll = value;
347
      v.type = SQL_C_SBIGINT;
348
      SQLRETURN rc = SQLBindParameter(
349
        /*StatementHandle: */stmt_,
350
        /*ParameterNumber: */column + 1,
351
        /*InputOutputType: */SQL_PARAM_INPUT,
352
        /*ValueType: */SQL_C_SBIGINT,
353
        /*ParameterType: */SQL_BIGINT,
354
        /*Columnsize: */0, // ignored
355
        /*DecimalDigits: */0, // ignored
356
        /*ParameterValuePtr: */&v.v.ll,
357
        /*BufferLength: */0,
358
        /*StrLen_or_IndPtr: */&v.lengthOrInd
359
      );
360
      handleErr(SQL_HANDLE_STMT, stmt_, rc);
361
    }
362
  }
363

  
364
  virtual void bind(int column, float value) override
365
  {
366
    checkColumnIndex(column);
367
    Value &v = paramValues_[column];
368
    if (v.type == SQL_C_FLOAT) {
369
      v.v.f = value;
370
      v.lengthOrInd = 0;
371
    } else {
372
      v.clear();
373
      v.v.f = value;
374
      v.type = SQL_C_FLOAT;
375
      SQLRETURN rc = SQLBindParameter(
376
        /*StatementHandle: */stmt_,
377
        /*ParameterNumber: */column + 1,
378
        /*InputOutputType: */SQL_PARAM_INPUT,
379
        /*ValueType: */SQL_C_FLOAT,
380
        /*ParameterType: */SQL_REAL,
381
        /*Columnsize: */0, // seems ignored?
382
        /*DecimalDigits: */0, // ignored
383
        /*ParameterValuePtr: */&v.v.f,
384
        /*BufferLength: */0,
385
        /*StrLen_or_IndPtr: */&v.lengthOrInd
386
      );
387
      handleErr(SQL_HANDLE_STMT, stmt_, rc);
388
    }
389
  }
390

  
391
  virtual void bind(int column, double value) override
392
  {
393
    checkColumnIndex(column);
394
    Value &v = paramValues_[column];
395
    if (v.type == SQL_C_DOUBLE) {
396
      v.v.d = value;
397
      v.lengthOrInd = 0;
398
    } else {
399
      v.clear();
400
      v.v.d = value;
401
      v.type = SQL_C_DOUBLE;
402
      SQLRETURN rc = SQLBindParameter(
403
        /*StatementHandle: */stmt_,
404
        /*ParameterNumber: */column + 1,
405
        /*InputOutputType: */SQL_PARAM_INPUT,
406
        /*ValueType: */SQL_C_DOUBLE,
407
        /*ParameterType: */SQL_DOUBLE,
408
        /*Columnsize: */0, // seems ignored?
409
        /*DecimalDigits: */0, // ignored
410
        /*ParameterValuePtr: */&v.v.d,
411
        /*BufferLength: */0,
412
        /*StrLen_or_IndPtr: */&v.lengthOrInd
413
      );
414
      handleErr(SQL_HANDLE_STMT, stmt_, rc);
415
    }
416
  }
417

  
418
  virtual void bind(
419
    int column,
420
    const std::chrono::system_clock::time_point& value,
421
    SqlDateTimeType type) override
422
  {
423
    checkColumnIndex(column);
424
    Value &v = paramValues_[column];
425
    if (type == SqlDateTimeType::Date) {
426
      if (v.type != SQL_C_TYPE_DATE)
427
        v.clear();
428
      v.lengthOrInd = 0;
429
      SQL_DATE_STRUCT &date = paramValues_[column].v.date;
430
      auto daypoint = date::floor<date::days>(value);
431
      auto ymd = date::year_month_day(daypoint);
432
      date.year = (int)ymd.year();
433
      date.month = (unsigned)ymd.month();
434
      date.day = (unsigned)ymd.day();
435
      if (v.type != SQL_C_TYPE_DATE) {
436
        v.type = SQL_C_TYPE_DATE;
437
        SQLRETURN rc = SQLBindParameter(
438
          /*StatementHandle: */stmt_,
439
          /*ParameterNumber: */column + 1,
440
          /*InputOutputType: */SQL_PARAM_INPUT,
441
          /*ValueType: */SQL_C_TYPE_DATE,
442
          /*ParameterType: */SQL_TYPE_DATE,
443
          /*ColumnSize: */0,
444
          /*DecimalDigits: */0,
445
          /*ParameterValuePtr: */&date,
446
          /*BufferLength: */0,
447
          /*StrLen_or_IndPtr: */&v.lengthOrInd
448
        );
449
        handleErr(SQL_HANDLE_STMT, stmt_, rc);
450
      }
451
    } else {
452
      if (v.type != SQL_C_TYPE_TIMESTAMP)
453
        v.clear();
454
      v.lengthOrInd = 0;
455
      SQL_TIMESTAMP_STRUCT &ts = paramValues_[column].v.timestamp;
456
      auto daypoint = date::floor<date::days>(value);
457
      auto ymd = date::year_month_day(daypoint);
458
      auto tod = date::make_time(value - daypoint);
459
      ts.year = (int)ymd.year();
460
      ts.month = (unsigned)ymd.month();
461
      ts.day = (unsigned)ymd.day();
462
      ts.hour = tod.hours().count();
463
      ts.minute = tod.minutes().count();
464
      ts.second = tod.seconds().count();
465
      ts.fraction = std::chrono::nanoseconds(std::chrono::duration_cast<
466
        std::chrono::duration<long long, std::ratio_multiply<std::ratio<100>, std::nano>>>(tod.subseconds())).count();
467
      if (v.type != SQL_C_TYPE_TIMESTAMP) {
468
        v.type = SQL_C_TYPE_TIMESTAMP;
469
        SQLRETURN rc = SQLBindParameter(
470
          /*StatementHandle: */stmt_,
471
          /*ParameterNumber: */column + 1,
472
          /*InputOutputType: */SQL_PARAM_INPUT,
473
          /*ValueType: */SQL_C_TYPE_TIMESTAMP,
474
          /*ParameterType: */SQL_TYPE_TIMESTAMP,
475
          /*ColumnSize: */0,
476
          /*DecimalDigits: */7, // SQL Server limit: max 7 decimal digits
477
          /*ParameterValuePtr: */&ts,
478
          /*BufferLength: */0,
479
          /*StrLen_or_IndPtr: */&v.lengthOrInd
480
        );
481
        handleErr(SQL_HANDLE_STMT, stmt_, rc);
482
      }
483
    }
484
  }
485

  
486
  virtual void bind(
487
    int column,
488
    const std::chrono::duration<int, std::milli>& value) override
489
  {
490
    long long msec = value.count();
491
    bind(column, msec);
492
  }
493

  
494
  virtual void bind(
495
    int column,
496
    const std::vector<unsigned char>& value) override
497
  {
498
    checkColumnIndex(column);
499
    Value &v = paramValues_[column];
500
    bool newPtr = createOrResizeBuffer(v, value.size());
501
    v.lengthOrInd = value.size();
502
    memcpy(v.v.buf.p, value.data(), value.size());
503
    if (newPtr || v.type != SQL_C_BINARY) {
504
      v.type = SQL_C_BINARY;
505
      SQLRETURN rc = SQLBindParameter(
506
        /*StatementHandle: */stmt_,
507
        /*ParameterNumber: */column + 1,
508
        /*InputOutputType: */SQL_PARAM_INPUT,
509
        /*ValueType: */SQL_C_BINARY,
510
        /*ParameterType: */SQL_VARBINARY,
511
        /*ColumnSize: */0, // ignored
512
        /*DecimalDigits: */0, // ignored
513
        /*ParameterValuePtr: */v.v.buf.p,
514
        /*BufferLength: */v.v.buf.size,
515
        /*StrLen_or_IndPtr: */&v.lengthOrInd
516
      );
517
      handleErr(SQL_HANDLE_STMT, stmt_, rc);
518
    }
519
  }
520

  
521
  virtual void bindNull(int column) override
522
  {
523
    checkColumnIndex(column);
524
    Value &v = paramValues_[column];
525
    if (v.type != 0)
526
      v.lengthOrInd = SQL_NULL_DATA;
527
    else {
528
      v.clear();
529
      v.type = SQL_C_CHAR;
530
      v.v.buf.p = 0;
531
      v.v.buf.size = SQL_NULL_DATA;
532
      SQLRETURN rc = SQLBindParameter(
533
        /*StatementHandle: */stmt_,
534
        /*ParameterNumber: */column + 1,
535
        /*InputOutputType: */SQL_PARAM_INPUT,
536
        /*ValueType: */SQL_C_CHAR,
537
        /*ParameterType: */SQL_VARCHAR,
538
        /*Columnsize: */0,
539
        /*DecimalDigits: */0,
540
        /*ParameterValuePtr: */NULL,
541
        /*BufferLength: */0,
542
        /*StrLen_or_IndPtr: */&v.v.buf.size
543
      );
544
      handleErr(SQL_HANDLE_STMT, stmt_, rc);
545
    }
546
  }
547

  
548
  virtual void execute() override
549
  {
550
    if (conn_.showQueries()) {
551
      LOG_INFO(sql_);
552
    }
553

  
554
    SQLRETURN rc = SQLExecute(stmt_);
555
    if (rc != SQL_NO_DATA) // SQL_NO_DATA can occur when no rows are affected
556
      handleErr(SQL_HANDLE_STMT, stmt_, rc);
557

  
558
    rc = SQLRowCount(stmt_, &affectedRows_);
559
    handleErr(SQL_HANDLE_STMT, stmt_, rc);
560
  }
561

  
562
  virtual long long insertedId() override
563
  {
564
      char *last_id = (char*)malloc(32);
565
      char *sql;
566
      SQLHANDLE hstmt;
567
      SQLLEN out_length;
568

  
569
      SQLAllocHandle(SQL_HANDLE_STMT, conn_.impl_->dbc, &hstmt);
570
      sql = (char*)"SELECT IDENTITY_VAL_LOCAL() FROM SYSIBM.SYSDUMMY1";
571
      SQLExecDirect(hstmt, (SQLCHAR*)sql, strlen(sql));
572
      SQLBindCol(hstmt, 1, SQL_C_CHAR, last_id, 32, &out_length);
573
      SQLFetch(hstmt);
574
      SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
575
      return std::atoi(last_id);
576
  }
577

  
578
  virtual int affectedRowCount() override
579
  {
580
    return static_cast<int>(affectedRows_);
581
  }
582

  
583
  virtual bool nextRow() override
584
  {
585
    SQLRETURN rc = SQLFetch(stmt_);
586
    if (rc == SQL_NO_DATA)
587
      return false;
588
    else {
589
      handleErr(SQL_HANDLE_STMT, stmt_, rc);
590
      return true;
591
    }
592
  }
593

  
594
  virtual int columnCount() const override
595
  {
596
    return resultColCount_;
597
  }
598

  
599
  virtual bool getResult(int column, std::string *value, int size) override
600
  {
601
    SQLCHAR colName[32];
602
    SQLSMALLINT colNameLen;
603
    SQLSMALLINT colType;
604
    SQLULEN colSize;
605
    SQLSMALLINT colScale;
606
    SQLLEN colDataDisplaySize;
607
    SQLDescribeCol(stmt_, (SQLSMALLINT)(column + 1), colName, sizeof(colName), &colNameLen, &colType, &colSize, &colScale, NULL);
608
    SQLColAttribute(stmt_, (SQLSMALLINT)(column + 1), SQL_DESC_DISPLAY_SIZE, NULL, 0, NULL, &colDataDisplaySize);
609

  
610
    DB2::Impl::ResultBuffer &resultBuffer = conn_.impl_->resultBuffer;
611
    std::size_t resultBufferPos = 0;
612
    SQLLEN strLen_or_ind = SQL_NO_TOTAL;
613
      SQLRETURN rc = SQLGetData(
614
        stmt_,
615
        column + 1,
616
#ifdef WT_WIN32
617
        SQL_C_WCHAR,
618
#else // WT_WIN32
619
        SQL_C_CHAR, // conversion from UTF-16 to UTF-8 done by driver
620
#endif // WT_WIN32
621
        &resultBuffer.buf[resultBufferPos],
622
        colSize,
623
        &strLen_or_ind
624
      );
625
      handleErr(SQL_HANDLE_STMT, stmt_, rc);
626
      if (strLen_or_ind == SQL_NULL_DATA) {
627
        return false; // NULL
628
      } else {
629
        resultBuffer.buf = reinterpret_cast<char*>(resultBuffer.buf);
630
        strLen_or_ind = strlen(resultBuffer.buf);
631
      }
632
    if (resultBufferPos == 0 && strLen_or_ind == 0) {
633
      value->clear();
634
      return true; // empty string
635
    }
636
    std::size_t totalDataSize = resultBufferPos + strLen_or_ind;
637
#ifdef WT_WIN32
638
    int strlen = WideCharToMultiByte(CP_UTF8, 0, (WCHAR*)resultBuffer.buf, totalDataSize / sizeof(WCHAR), NULL, 0, NULL, NULL);
639
    assert(strlen != 0);
640
    value->clear();
641
    value->resize(strlen);
642
    strlen = WideCharToMultiByte(CP_UTF8, 0, (WCHAR*)resultBuffer.buf, totalDataSize / sizeof(WCHAR), &(*value)[0], strlen, NULL, NULL);
643
    assert(strlen != 0);
644
#else // WT_WIN32
645
    *value = std::string(resultBuffer.buf, totalDataSize);
646
#endif // WT_WIN32
647
    return true;
648
  }
649

  
650
  virtual bool getResult(int column, short * value) override
651
  {
652
    return getRes<SQL_C_SSHORT>(column, value);
653
  }
654

  
655
  virtual bool getResult(int column, int * value) override
656
  {
657
    return getRes<SQL_C_SLONG>(column, value);
658
  }
659

  
660
  virtual bool getResult(int column, long long * value) override
661
  {
662
    return getRes<SQL_C_SBIGINT>(column, value);
663
  }
664

  
665
  virtual bool getResult(int column, float * value) override
666
  {
667
    return getRes<SQL_C_FLOAT>(column, value);
668
  }
669

  
670
  virtual bool getResult(int column, double * value) override
671
  {
672
    return getRes<SQL_C_DOUBLE>(column, value);
673
  }
674

  
675
  virtual bool getResult(
676
    int column,
677
    std::chrono::system_clock::time_point *value,
678
    SqlDateTimeType type) override
679
  {
680
    if (type == SqlDateTimeType::Date) {
681
      SQL_DATE_STRUCT date;
682
      bool result = getRes<SQL_C_TYPE_DATE>(column, &date);
683
      if (!result)
684
        return false; // NULL
685
      *value = date::sys_days{ date::year{ date.year } / date.month / date.day };
686
      return true;
687
    } else {
688
      SQL_TIMESTAMP_STRUCT ts;
689
      bool result = getRes<SQL_C_TYPE_TIMESTAMP>(column, &ts);
690
      if (!result)
691
        return false; // NULL
692
      *value = 
693
        date::sys_days{ date::year{ ts.year } / ts.month / ts.day } +
694
        std::chrono::duration_cast<std::chrono::system_clock::duration>(
695
          std::chrono::hours{ ts.hour } +
696
          std::chrono::minutes{ ts.minute } +
697
          std::chrono::seconds{ ts.second } +
698
          std::chrono::nanoseconds{ ts.fraction }
699
        );
700
      return true;
701
    }
702
    assert(false);
703
    return false;
704
  }
705

  
706
  virtual bool getResult(
707
    int column,
708
    std::chrono::duration<int, std::milli> *value) override
709
  {
710
    long long msec;
711
    bool res = getResult(column, &msec);
712
    if (!res)
713
      return res;
714

  
715
    *value = std::chrono::duration<int, std::milli>(msec);
716
    return true;
717
  }
718

  
719
  virtual bool getResult(
720
    int column,
721
    std::vector<unsigned char> *value,
722
    int) override
723
  {
724
    DB2::Impl::ResultBuffer &resultBuffer = conn_.impl_->resultBuffer;
725
    std::size_t resultBufferPos = 0;
726
    SQLLEN strLen_or_ind = SQL_NO_TOTAL;
727
    while (strLen_or_ind == SQL_NO_TOTAL) {
728
      SQLRETURN rc = SQLGetData(
729
        /*StatementHandle: */stmt_,
730
        /*ColumnNumber: */column + 1,
731
        /*TargetType: */SQL_C_BINARY,
732
        /*TargetValue: */&resultBuffer.buf[resultBufferPos],
733
        /*BufferLength: */resultBuffer.size - resultBufferPos,
734
        /*StrLen_or_IndPtr: */&strLen_or_ind
735
      );
736
      handleErr(SQL_HANDLE_STMT, stmt_, rc);
737
      if (strLen_or_ind == SQL_NULL_DATA) {
738
        return false; // NULL
739
      } else if (strLen_or_ind == SQL_NO_TOTAL || strLen_or_ind > resultBuffer.size - resultBufferPos) {
740
        std::size_t pos = resultBuffer.size;
741
        resultBuffer.size *= 2;
742
        while (strLen_or_ind != SQL_NO_TOTAL &&
743
               strLen_or_ind > resultBuffer.size - resultBufferPos)
744
          resultBuffer.size *= 2;
745
        resultBufferPos = pos;
746
        resultBuffer.buf = (char*)realloc(resultBuffer.buf, resultBuffer.size);
747
        strLen_or_ind = SQL_NO_TOTAL;
748
      }
749
    }
750
    std::size_t totalDataSize = resultBufferPos + strLen_or_ind;
751
    *value = std::vector<unsigned char>(resultBuffer.buf, resultBuffer.buf + totalDataSize);
752
    return true;
753
  }
754

  
755
  virtual std::string sql() const override
756
  {
757
    return sql_;
758
  }
759

  
760
private:
761
  struct Value {
762
    union {
763
      struct {
764
        void *p; // buffer pointer 
765
        SQLLEN size; // buffer size
766
      } buf;
767
      short s;
768
      int i;
769
      long long ll;
770
      float f;
771
      double d;
772
      SQL_DATE_STRUCT date;
773
      SQL_TIME_STRUCT time;
774
      SQL_TIMESTAMP_STRUCT timestamp;
775
    } v;
776
    SQLLEN lengthOrInd; // length for binary data or string or NULL indicator
777
    SQLSMALLINT type; // SQL_C... type
778

  
779
    Value()
780
    {
781
      std::memset(&v, 0, sizeof(v));
782
      lengthOrInd = 0;
783
      type = 0;
784
    }
785

  
786
    ~Value()
787
    {
788
      if (type == SQL_C_BINARY ||
789
          type == SQL_C_WCHAR)
790
        free(v.buf.p);
791
    }
792

  
793
#ifdef WT_CXX11
794
    Value(const Value &other) = delete;
795
    Value &operator=(const Value &other) = delete;
796
    Value(Value &&other) = delete;
797
    Value &operator=(Value &&other) = delete;
798
#endif // WT_CXX11
799

  
800
    void clear()
801
    {
802
      if (type == SQL_C_BINARY ||
803
          type == SQL_C_WCHAR)
804
        free(v.buf.p);
805

  
806
      std::memset(&v, 0, sizeof(v));
807
      lengthOrInd = 0;
808
      type = 0;
809
    }
810

  
811
  private:
812
#ifndef WT_CXX11
813
    Value(const Value &other);
814
    Value& operator=(const Value &other);
815
#endif // WT_CXX11
816
  };
817
  Value *paramValues_;
818
  SQLSMALLINT parameterCount_;
819
  SQLSMALLINT resultColCount_;
820

  
821
  SQLHSTMT stmt_;
822
  DB2 &conn_;
823
  std::string sql_;
824
  SQLLEN affectedRows_;
825
  long long lastId_;
826

  
827
  void checkColumnIndex(int column)
828
  {
829
    if (column >= parameterCount_)
830
      throw DB2ServerException(
831
        std::string("Trying to bind too many parameters (parameter count = ") +
832
          std::to_string(parameterCount_) +
833
          ", column = " +
834
          std::to_string(column) +
835
          std::string(")"));
836
  }
837

  
838
  // bool returns whether buffer changed
839
  bool createOrResizeBuffer(Value &v, SQLLEN size)
840
  {
841
    if (v.type == SQL_C_WCHAR || v.type == SQL_C_BINARY) {
842
      // We already have a buffer
843
      if (v.v.buf.size >= size)
844
        return false;
845
      v.v.buf.size = size;
846
      v.v.buf.p = realloc(v.v.buf.p, v.v.buf.size);
847
      return true;
848
    }
849
    else {
850
      // New buffer
851
      v.clear();
852
      v.v.buf.size = size == 0 ? 1 : size;
853
      v.v.buf.p = malloc(v.v.buf.size);
854
      return true;
855
    }
856
  }
857

  
858
  template<SQLSMALLINT TargetType, typename ReturnType>
859
  bool getRes(int column, ReturnType * value)
860
  {
861
    SQLLEN strLen_or_ind = 0;
862
    SQLRETURN rc = SQLGetData(
863
      /*StatementHandle: */stmt_,
864
      /*ColumnNumber: */column + 1,
865
      /*TargetType: */TargetType,
866
      /*TargetValue: */value,
867
      /*BufferLength: */0,
868
      /*StrLen_or_IndPtr*/&strLen_or_ind
869
    );
870
    handleErr(SQL_HANDLE_STMT, stmt_, rc);
871
    return rc == 0;
872
  }
873
};
874

  
875
DB2::DB2()
876
  : impl_(0)
877
{ }
878

  
879
DB2::DB2(const std::string &connectionString)
880
  : impl_(0)
881
{
882
  connect(connectionString);
883
}
884

  
885
DB2::DB2(const DB2 &other)
886
  : SqlConnection(other),
887
    impl_(other.impl_ ? new Impl(*other.impl_) : 0)
888
{
889
  if (impl_)
890
    impl_->connect();
891
}
892

  
893
DB2::~DB2()
894
{
895
  clearStatementCache();
896
  delete impl_;
897
}
898

  
899
std::unique_ptr<SqlConnection> DB2::clone() const
900
{
901
  return std::unique_ptr<SqlConnection>(new DB2(*this));
902
}
903

  
904
bool DB2::connect(const std::string &connectionString)
905
{
906
  if (impl_)
907
    throw DB2ServerException("Can't connect: already connected.");
908

  
909
#ifdef WT_WIN32
910
  ConnectionStringType connStr;
911
  if (!connectionString.empty()) {
912
    int wstrlen = MultiByteToWideChar(CP_UTF8, 0, &connectionString[0], connectionString.size(), 0, 0);
913
    assert(wstrlen != 0);
914
    connStr.resize(wstrlen);
915
    wstrlen = MultiByteToWideChar(CP_UTF8, 0, &connectionString[0], connectionString.size(), &connStr[0], connStr.size());
916
    assert(wstrlen != 0);
917
  }
918
#else // WT_WIN32
919
  ConnectionStringType connStr = toUTF16(connectionString);
920
#endif // WT_WIN32
921

  
922
  Impl *impl = new Impl(connStr);
923
  try {
924
    impl->connect();
925
  } catch (...) {
926
    delete impl;
927
    throw;
928
  }
929

  
930
  impl_ = impl;
931
  return true;
932
}
933

  
934
void DB2::executeSql(const std::string &sql)
935
{
936
  if (showQueries()) {
937
    LOG_INFO(sql);
938
  }
939

  
940
  SQLRETURN rc = SQL_SUCCESS;
941
  if (!impl_->stmt) {
942
    rc = SQLAllocHandle(SQL_HANDLE_STMT, impl_->dbc, &impl_->stmt);
943
    handleErr(SQL_HANDLE_DBC, impl_->dbc, rc);
944
  }
945
#ifdef WT_WIN32
946
  if (sql.empty()) {
947
    SQLWCHAR wstr[] = L"";
948
    rc = SQLExecDirectW(impl_->stmt, wstr, 0);
949
  } else {
950
    int wstrlen = MultiByteToWideChar(CP_UTF8, 0, &sql[0], sql.size(), 0, 0);
951
    assert(wstrlen != 0);
952
    SQLWCHAR *wstr = new SQLWCHAR[wstrlen + 1];
953
    wstrlen = MultiByteToWideChar(CP_UTF8, 0, &sql[0], sql.size(), wstr, wstrlen);
954
    assert(wstrlen != 0);
955
    wstr[wstrlen] = 0;
956
    rc = SQLExecDirectW(impl_->stmt, wstr, wstrlen);
957
    delete[] wstr;
958
  }
959
#else // WT_WIN32
960
  std::u16string wstr = toUTF16(sql);
961
  rc = SQLExecDirectW(impl_->stmt, (SQLWCHAR*)&wstr[0], wstr.size());
962
#endif // WT_WIN32
963
  try {
964
    handleErr(SQL_HANDLE_STMT, impl_->stmt, rc);
965
  } catch (...) {
966
    SQLFreeStmt(impl_->stmt, SQL_CLOSE);
967
    throw;
968
  }
969
  SQLFreeStmt(impl_->stmt, SQL_CLOSE);
970
}
971

  
972
void DB2::startTransaction()
973
{
974
  if (showQueries()) {
975
    LOG_INFO("begin transaction -- implicit");
976
  }
977
}
978

  
979
void DB2::commitTransaction()
980
{
981
  if (showQueries()) {
982
    LOG_INFO("commit transaction -- using SQLEndTran");
983
  }
984

  
985
  SQLRETURN rc = SQLEndTran(SQL_HANDLE_DBC, impl_->dbc, SQL_COMMIT);
986
  handleErr(SQL_HANDLE_DBC, impl_->dbc, rc);
987
}
988

  
989
void DB2::rollbackTransaction()
990
{
991
  if (showQueries()) {
992
    LOG_INFO("rollback transaction -- using SQLEndTran");
993
  }
994

  
995
  SQLRETURN rc = SQLEndTran(SQL_HANDLE_DBC, impl_->dbc, SQL_ROLLBACK);
996
  handleErr(SQL_HANDLE_DBC, impl_->dbc, rc);
997
}
998

  
999
std::unique_ptr<SqlStatement> DB2::prepareStatement(const std::string &sql)
1000
{
1001
  return std::unique_ptr<SqlStatement>(new DB2ServerStatement(*this, sql));
1002
}
1003

  
1004
std::string DB2::autoincrementSql() const
1005
{
1006
  return "not null GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1)";
1007
}
1008

  
1009
std::vector<std::string> DB2::autoincrementCreateSequenceSql(const std::string &table, const std::string &id) const
1010
{
1011
  return std::vector<std::string>();
1012
}
1013

  
1014
std::vector<std::string> DB2::autoincrementDropSequenceSql(const std::string &table, const std::string &id) const
1015
{
1016
  return std::vector<std::string>();
1017
}
1018

  
1019
std::string DB2::autoincrementType() const
1020
{
1021
  return "bigint";
1022
}
1023

  
1024
std::string DB2::autoincrementInsertSuffix(const std::string &id) const
1025
{
1026
  return "";
1027
}
1028

  
1029
const char *DB2::dateTimeType(SqlDateTimeType type) const
1030
{
1031
  if (type == SqlDateTimeType::Date)
1032
    return "date";
1033
  if (type == SqlDateTimeType::Time)
1034
    return "bigint"; // SQL Server has no proper duration type, so store duration as number of milliseconds
1035
  if (type == SqlDateTimeType::DateTime)
1036
    return "timestamp";
1037
  return "";
1038
}
1039

  
1040
bool DB2::requireSubqueryAlias() const
1041
{
1042
  return true;
1043
}
1044

  
1045
const char *DB2::blobType() const
1046
{
1047
  return "varbinary(max)";
1048
}
1049

  
1050
const char *DB2::booleanType() const
1051
{
1052
  return "smallint";
1053
}
1054

  
1055
bool DB2::supportAlterTable() const
1056
{
1057
  return true;
1058
}
1059

  
1060
std::string DB2::textType(int size) const
1061
{
1062
  if (size == -1)
1063
    return "varchar(32672)";
1064
  else
1065
    return std::string("varchar(") + std::to_string(size) + ")";
1066
}
1067

  
1068
LimitQuery DB2::limitQueryMethod() const
1069
{
1070
  return LimitQuery::OffsetFetch;
1071
}
1072

  
1073
    }
1074
  }
1075
}
wt-4.5.0-patched/src/Wt/Dbo/backend/DB2.h 2021-04-20 16:48:27.289256974 +0200
1
// This may look like C code, but it's really -*- C++ -*-
2
/*
3
 * Copyright (C) 2017 Emweb bv, Herent, Belgium.
4
 *
5
 * See the LICENSE file for terms of use.
6
 */
7
#ifndef WT_DBO_BACKEND_DB2SERVER_H_
8
#define WT_DBO_BACKEND_DB2SERVER_H_
9

  
10
#include <Wt/Dbo/SqlConnection.h>
11
#include <Wt/Dbo/SqlStatement.h>
12
#include "WDboDB2DllDefs.h"
13

  
14
namespace Wt {
15
  namespace Dbo {
16
    namespace backend {
17

  
18
/*! \class DB2SErver Wt/Dbo/backend/DB2Server Wt/Dbo/backend/DB2Server
19
 *  \brief A DB2 SQL Server connection
20
 *
21
 * This class provides the backend implementation for DB2 Server databases.
22
 *
23
 * \ingroup dbo
24
 */
25
class WTDBODB2_API DB2 : public SqlConnection
26
{
27
public:
28
  /*! \brief Creates a new DB2 SQL Server backend connection.
29
   *
30
   * The connection is not yet open, and requires a connect() before it
31
   * can be used.
32
   */
33
  DB2();
34

  
35
  /*! \brief Creates a new DB2 Server backend connection.
36
   *
37
   * For info about the connection string, see the connect() method.
38
   *
39
   * \sa connect()
40
   */
41
  DB2(const std::string &connectionString);
42

  
43
  /*! \brief Copy constructor.
44
   *
45
   * This creates a new backend connection with the same settings
46
   * as another connection.
47
   *
48
   * \sa clone()
49
   */
50
  DB2(const DB2& other);
51

  
52
  /*! \brief Destructor.
53
   *
54
   * Closes the connection.
55
   */
56
  virtual ~DB2();
57

  
58
  virtual std::unique_ptr<Wt::Dbo::SqlConnection> clone() const override;
59

  
60
  /*! \brief Tries to connect.
61
   *
62
   * Throws an exception if there was a problem, otherwise returns true.
63
   *
64
   * The connection string is the connection string that should be passed
65
   * to SQLDriverConnectW to connect to the DB2 Server database.
66
   *
67
   * The \p connectionString should be UTF-8 encoded.
68
   *
69
   * Example connection string:
70
   *
71
   * \code
72
   * Driver={ODBC Driver DB2};
73
   * Server=localhost; 
74
   * UID=SA;
75
   * PWD={example password};
76
   * Database=example_db;
77
   * \endcode
78
   *
79
   * You could also specify a DSN (Data Source Name) if you have it configured.
80
   *
81
   * See the
82
   * <a href="https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqldriverconnect-function">SQLDriverConnect</a>
83
   * function documentation on MSDN for more info.
84
   */
85
  bool connect(const std::string &connectionString);
86

  
87
  virtual void executeSql(const std::string &sql) override;
88

  
89
  virtual void startTransaction() override;
90
  virtual void commitTransaction() override;
91
  virtual void rollbackTransaction() override;
92
  
93
  virtual std::unique_ptr<SqlStatement> prepareStatement(const std::string &sql) override;
94

  
95
  /** @name Methods that return dialect information
96
   */
97
  //!@{
98
  virtual std::string autoincrementSql() const override;
99
  virtual std::vector<std::string> autoincrementCreateSequenceSql(const std::string &table, const std::string &id) const override;
100
  virtual std::vector<std::string> autoincrementDropSequenceSql(const std::string &table, const std::string &id) const override;
101
  virtual std::string autoincrementType() const override;
102
  virtual std::string autoincrementInsertSuffix(const std::string &id) const override;
103
  virtual const char *dateTimeType(SqlDateTimeType type) const override;
104
  virtual const char *blobType() const override;
105
  virtual bool requireSubqueryAlias() const override;
106
  virtual const char *booleanType() const override;
107
  virtual bool supportAlterTable() const override;
108
  virtual std::string textType(int size) const override;
109
  virtual LimitQuery limitQueryMethod() const override;
110
  //!@}
111

  
112
private:
113
  struct Impl;
114
  Impl *impl_;
115

  
116
  friend class DB2ServerStatement;
117
};
118

  
119
    }
120
  }
121
}
122

  
123
#endif // WT_DBO_BACKEND_MSSQLSERVER_H_
wt-4.5.0-patched/src/Wt/Dbo/backend/WDboDB2DllDefs.h 2021-04-20 16:48:27.293256939 +0200
1
// This may look like C code, but it's really -*- C++ -*-
2
/*
3
* Copyright (C) 2017 Emweb bv, Herent, Belgium.
4
*
5
* See the LICENSE file for terms of use.
6
*/
7
#ifndef WDBODB2DLLDEFS_H_
8
#define WDBODB2DLLDEFS_H_
9

  
10
#include <Wt/WConfig.h>
11

  
12
// Source: http://www.nedprod.com/programs/gccvisibility.html
13

  
14
#ifdef WT_WIN32
15
  #define WTDBODB2_IMPORT __declspec(dllimport)
16
  #define WTDBODB2_EXPORT __declspec(dllexport)
17
  #define WTDBODB2_DLLLOCAL
18
  #define WTDBODB2_DLLPUBLIC
19
#else
20
  #define WTDBODB2_IMPORT __attribute__ ((visibility("default")))
21
  #define WTDBODB2_EXPORT __attribute__ ((visibility("default")))
22
  #define WTDBODB2_DLLLOCAL __attribute__ ((visibility("hidden")))
23
  #define WTDBODB2_DLLPUBLIC __attribute__ ((visibility("default")))
24
#endif
25

  
26
#ifdef WTDBODB2_EXPORTS
27
  #define WTDBODB2_API WTDBODB2_EXPORT
28
#else
29
  #ifdef WTDBODB2_STATIC
30
    #define WTDBODB2_API
31
  #else
32
    #define WTDBODB2_API WTDBODB2_IMPORT
33
  #endif
34
#endif
35

  
36
#endif // WDBOMSSQLSERVERDLLDEFS_H_
wt-4.5.0-patched/src/Wt/Dbo/backend/wtdbodb2-version.rc.in 2021-04-20 16:48:27.293256939 +0200
1
/* Template from MSDN */
2
#include <windows.h>
3

  
4

  
5
#define VER_PRODUCTVERSION    @VERSION_SERIES@,@VERSION_MAJOR@,@VERSION_MINOR@,0
6
#define VER_PRODUCTVERSION_STR "@VERSION_SERIES@.@VERSION_MAJOR@.@VERSION_MINOR@"
7
#define VER_FILEVERSION       @VERSION_SERIES@,@VERSION_MAJOR@,@VERSION_MINOR@,0
8
#define VER_FILEVERSION_STR   "@VERSION_SERIES@.@VERSION_MAJOR@.@VERSION_MINOR@"
9
#define VER_COMPANYNAME_STR   "Emweb bv, Belgium"
10
#define VER_FILEDESCRIPTION_STR "Wt C++ Dbo Microsoft SQL Server backend DLL"
11
#define VER_INTERNALNAME_STR ""
12
#define VER_LEGALCOPYRIGHT_STR "(c) 2020 Emweb bv, Belgium. See LICENSE file for details"
13
#define VER_PRODUCTNAME_STR "Wt C++ Wt::DBO Microsoft SQL Server backend"
14
#define VER_ORIGINALFILENAME_STR "wtdbomssqlserver.dll"
15

  
16
#ifndef DEBUG
17
#define VER_DEBUG                   0
18
#else
19
#define VER_DEBUG                   VS_FF_DEBUG
20
#endif
21

  
22
#define VER_PRIVATEBUILD 0
23
#define VER_PRERELEASE 0
24

  
25
VS_VERSION_INFO VERSIONINFO
26
FILEVERSION    	VER_FILEVERSION
27
PRODUCTVERSION 	VER_PRODUCTVERSION
28
FILEFLAGSMASK  	VS_FFI_FILEFLAGSMASK
29
FILEFLAGS      	(VER_PRIVATEBUILD|VER_PRERELEASE|VER_DEBUG)
30
FILEOS         	VOS__WINDOWS32
31
FILETYPE       	VFT_DLL
32
FILESUBTYPE    	VFT2_UNKNOWN
33
BEGIN
34
    BLOCK "StringFileInfo"
35
    BEGIN
36
        BLOCK "040904E4"
37
        BEGIN
38
            VALUE "CompanyName",      VER_COMPANYNAME_STR
39
            VALUE "FileDescription",  VER_FILEDESCRIPTION_STR
40
            VALUE "FileVersion",      VER_FILEVERSION_STR
41
            VALUE "InternalName",     VER_INTERNALNAME_STR
42
            VALUE "LegalCopyright",   VER_LEGALCOPYRIGHT_STR
43
            VALUE "OriginalFilename", VER_ORIGINALFILENAME_STR
44
            VALUE "ProductName",      VER_PRODUCTNAME_STR
45
            VALUE "ProductVersion",   VER_PRODUCTVERSION_STR
46
        END
47
    END
48

  
49
    BLOCK "VarFileInfo"
50
    BEGIN
51
        VALUE "Translation", 0x409, 1252
52
    END
53
END
    (1-1/1)