Преглед изворни кода

项目配置更新

增加debug参数

更新三方库

稳定性优化

增加模块:http客户端、编解码、sqlserver客户端、时间、锁
xx пре 2 година
родитељ
комит
264860205d
100 измењених фајлова са 11716 додато и 107 уклоњено
  1. 5 0
      3rdparty/soci/include/private/README.md
  2. 266 0
      3rdparty/soci/include/private/firebird/common.h
  3. 35 0
      3rdparty/soci/include/private/firebird/error-firebird.h
  4. 42 0
      3rdparty/soci/include/private/soci-autostatement.h
  5. 39 0
      3rdparty/soci/include/private/soci-compiler.h
  6. 30 0
      3rdparty/soci/include/private/soci-cpp.h
  7. 80 0
      3rdparty/soci/include/private/soci-cstrtod.h
  8. 87 0
      3rdparty/soci/include/private/soci-cstrtoi.h
  9. 58 0
      3rdparty/soci/include/private/soci-dtocstr.h
  10. 129 0
      3rdparty/soci/include/private/soci-exchange-cast.h
  11. 69 0
      3rdparty/soci/include/private/soci-mktime.h
  12. 82 0
      3rdparty/soci/include/private/soci-trivial-blob-backend.h
  13. 157 0
      3rdparty/soci/include/private/soci-vector-helpers.h
  14. 40 0
      3rdparty/soci/include/soci/backend-loader.h
  15. 216 0
      3rdparty/soci/include/soci/bind-values.h
  16. 59 0
      3rdparty/soci/include/soci/blob-exchange.h
  17. 84 0
      3rdparty/soci/include/soci/blob.h
  18. 28 0
      3rdparty/soci/include/soci/boost-fusion.h
  19. 50 0
      3rdparty/soci/include/soci/boost-gregorian-date.h
  20. 92 0
      3rdparty/soci/include/soci/boost-optional.h
  21. 18 0
      3rdparty/soci/include/soci/boost-tuple.h
  22. 47 0
      3rdparty/soci/include/soci/callbacks.h
  23. 149 0
      3rdparty/soci/include/soci/column-info.h
  24. 99 0
      3rdparty/soci/include/soci/connection-parameters.h
  25. 41 0
      3rdparty/soci/include/soci/connection-pool.h
  26. 293 0
      3rdparty/soci/include/soci/db2/soci-db2.h
  27. 194 0
      3rdparty/soci/include/soci/empty/soci-empty.h
  28. 66 0
      3rdparty/soci/include/soci/error.h
  29. 190 0
      3rdparty/soci/include/soci/exchange-traits.h
  30. 356 0
      3rdparty/soci/include/soci/firebird/soci-firebird.h
  31. 155 0
      3rdparty/soci/include/soci/fixed-size-ints.h
  32. 213 0
      3rdparty/soci/include/soci/into-type.h
  33. 97 0
      3rdparty/soci/include/soci/into.h
  34. 49 0
      3rdparty/soci/include/soci/is-detected.h
  35. 82 0
      3rdparty/soci/include/soci/logger.h
  36. 314 0
      3rdparty/soci/include/soci/mysql/soci-mysql.h
  37. 22 0
      3rdparty/soci/include/soci/noreturn.h
  38. 624 0
      3rdparty/soci/include/soci/odbc/soci-odbc.h
  39. 183 0
      3rdparty/soci/include/soci/once-temp-type.h
  40. 492 0
      3rdparty/soci/include/soci/oracle/soci-oracle.h
  41. 442 0
      3rdparty/soci/include/soci/postgresql/soci-postgresql.h
  42. 65 0
      3rdparty/soci/include/soci/prepare-temp-type.h
  43. 90 0
      3rdparty/soci/include/soci/procedure.h
  44. 57 0
      3rdparty/soci/include/soci/query_transformation.h
  45. 66 0
      3rdparty/soci/include/soci/ref-counted-prepare-info.h
  46. 102 0
      3rdparty/soci/include/soci/ref-counted-statement.h
  47. 80 0
      3rdparty/soci/include/soci/row-exchange.h
  48. 202 0
      3rdparty/soci/include/soci/row.h
  49. 59 0
      3rdparty/soci/include/soci/rowid-exchange.h
  50. 41 0
      3rdparty/soci/include/soci/rowid.h
  51. 241 0
      3rdparty/soci/include/soci/rowset.h
  52. 239 0
      3rdparty/soci/include/soci/session.h
  53. 591 0
      3rdparty/soci/include/soci/soci-backend.h
  54. 16 0
      3rdparty/soci/include/soci/soci-config.h
  55. 197 0
      3rdparty/soci/include/soci/soci-platform.h
  56. 244 0
      3rdparty/soci/include/soci/soci-simple.h
  57. 15 0
      3rdparty/soci/include/soci/soci-types.h
  58. 63 0
      3rdparty/soci/include/soci/soci.h
  59. 384 0
      3rdparty/soci/include/soci/sqlite3/soci-sqlite3.h
  60. 329 0
      3rdparty/soci/include/soci/statement.h
  61. 55 0
      3rdparty/soci/include/soci/std-optional.h
  62. 36 0
      3rdparty/soci/include/soci/transaction.h
  63. 149 0
      3rdparty/soci/include/soci/type-conversion-traits.h
  64. 509 0
      3rdparty/soci/include/soci/type-conversion.h
  65. 449 0
      3rdparty/soci/include/soci/type-holder.h
  66. 30 0
      3rdparty/soci/include/soci/type-ptr.h
  67. 33 0
      3rdparty/soci/include/soci/type-wrappers.h
  68. 340 0
      3rdparty/soci/include/soci/use-type.h
  69. 123 0
      3rdparty/soci/include/soci/use.h
  70. 150 0
      3rdparty/soci/include/soci/values-exchange.h
  71. 351 0
      3rdparty/soci/include/soci/values.h
  72. 34 0
      3rdparty/soci/include/soci/version.h
  73. 1 1
      3rdparty/ylib/include/util/ini.h
  74. 3 2
      config.ini
  75. 18 13
      fastweb.vcxproj
  76. 30 24
      fastweb.vcxproj.filters
  77. 1 0
      src/core/config.cpp
  78. 1 0
      src/core/config.h
  79. 2 2
      src/core/define.h
  80. 6 1
      src/core/fastweb.cpp
  81. 15 0
      src/core/global.cpp
  82. 6 1
      src/core/global.h
  83. 2 2
      src/core/main.cpp
  84. 34 4
      src/core/statemanager.cpp
  85. 37 0
      src/module/codec.cpp
  86. 37 0
      src/module/codec.h
  87. 12 2
      src/module/globalfuns.cpp
  88. 3 6
      src/module/globalfuns.h
  89. 58 0
      src/module/http/httpclient.cpp
  90. 25 0
      src/module/http/httpclient.h
  91. 29 28
      src/module/http/request.cpp
  92. 5 3
      src/module/http/request.h
  93. 1 0
      src/module/imodule.h
  94. 0 3
      src/module/localstorage.h
  95. 76 0
      src/module/mssql.cpp
  96. 54 0
      src/module/mssql.h
  97. 58 0
      src/module/mutex.cpp
  98. 47 0
      src/module/mutex.h
  99. 39 13
      src/module/mysql.cpp
  100. 2 2
      src/module/mysql.h

+ 5 - 0
3rdparty/soci/include/private/README.md

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

+ 266 - 0
3rdparty/soci/include/private/firebird/common.h

@@ -0,0 +1,266 @@
+//
+// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, Rafal Bobrowski
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_FIREBIRD_COMMON_H_INCLUDED
+#define SOCI_FIREBIRD_COMMON_H_INCLUDED
+
+#include "soci/firebird/soci-firebird.h"
+#include "soci-compiler.h"
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+#include <limits>
+#include <sstream>
+#include <iomanip>
+#include <string>
+#include <vector>
+#include <algorithm>
+
+namespace soci
+{
+
+namespace details
+{
+
+namespace firebird
+{
+
+char * allocBuffer(XSQLVAR* var);
+
+void tmEncode(short type, std::tm * src, void * dst);
+
+void tmDecode(short type, void * src, std::tm * dst);
+
+void setTextParam(char const * s, std::size_t size, char * buf_,
+    XSQLVAR * var);
+
+std::string getTextParam(XSQLVAR const *var);
+
+// Copy contents of a BLOB in buf into the given string.
+void copy_from_blob(firebird_statement_backend &st, char *buf, std::string &out);
+
+template <typename IntType>
+const char *str2dec(const char * s, IntType &out, short &scale)
+{
+    int sign = 1;
+    if ('+' == *s)
+        ++s;
+    else if ('-' == *s)
+    {
+        sign = -1;
+        ++s;
+    }
+    scale = 0;
+    bool period = false;
+    IntType res = 0;
+    for (out = 0; *s; ++s, out = res)
+    {
+        if (*s == '.')
+        {
+            if (period)
+                return s;
+            period = true;
+            continue;
+        }
+        int d = *s - '0';
+        if (d < 0 || d > 9)
+            return s;
+        res = res * 10 + static_cast<IntType>(d * sign);
+        if (1 == sign)
+        {
+            if (res < out)
+                return s;
+        }
+        else
+        {
+            if (res > out)
+                return s;
+        }
+        if (period)
+            ++scale;
+    }
+    return s;
+}
+
+template <typename T>
+inline
+T round_for_isc(T value)
+{
+  return value;
+}
+
+inline
+double round_for_isc(double value)
+{
+  // Unfortunately all the rounding functions are C99 and so are not supported
+  // by MSVC, so do it manually.
+  return value < 0 ? value - 0.5 : value + 0.5;
+}
+
+//helper template to generate proper code based on compile time type check
+template<bool cond> struct cond_to_isc {};
+template<> struct cond_to_isc<false>
+{
+    static void checkInteger(short scale, short type)
+    {
+        if( scale >= 0 && (type == SQL_SHORT || type == SQL_LONG || type == SQL_INT64) )
+            throw soci_error("Can't convert non-integral value to integral column type");
+    }
+};
+template<> struct cond_to_isc<true>
+{
+    static void checkInteger(short scale,short type) { SOCI_UNUSED(scale) SOCI_UNUSED(type) }
+};
+
+template<typename T1>
+void to_isc(void * val, XSQLVAR * var, short x_scale = 0)
+{
+    T1 value = *reinterpret_cast<T1*>(val);
+    short scale = var->sqlscale + x_scale;
+    short type = var->sqltype & ~1;
+    long long divisor = 1, multiplier = 1;
+
+    cond_to_isc<std::numeric_limits<T1>::is_integer>::checkInteger(scale,type);
+
+    for (int i = 0; i > scale; --i)
+        multiplier *= 10;
+    for (int i = 0; i < scale; ++i)
+        divisor *= 10;
+
+    switch (type)
+    {
+    case SQL_SHORT:
+        {
+            int16_t tmp = static_cast<int16_t>(round_for_isc(value*multiplier)/divisor);
+            std::memcpy(var->sqldata, &tmp, sizeof(int16_t));
+        }
+        break;
+    case SQL_LONG:
+        {
+            int32_t tmp = static_cast<int32_t>(round_for_isc(value*multiplier)/divisor);
+            std::memcpy(var->sqldata, &tmp, sizeof(int32_t));
+        }
+        break;
+    case SQL_INT64:
+        {
+            int64_t tmp = static_cast<int64_t>(round_for_isc(value*multiplier)/divisor);
+            std::memcpy(var->sqldata, &tmp, sizeof(int64_t));
+        }
+        break;
+    case SQL_FLOAT:
+        {
+            float sql_value = static_cast<float>(value);
+            std::memcpy(var->sqldata, &sql_value, sizeof(float));
+        }
+        break;
+    case SQL_DOUBLE:
+        {
+            double sql_value = static_cast<double>(value);
+            std::memcpy(var->sqldata, &sql_value, sizeof(double));
+        }
+        break;
+    default:
+        throw soci_error("Incorrect data type for numeric conversion");
+    }
+}
+
+template<typename IntType, typename UIntType>
+void parse_decimal(void * val, XSQLVAR * var, const char * s)
+{
+    short scale;
+    UIntType t1;
+    IntType t2;
+    if (!*str2dec(s, t1, scale))
+        std::memcpy(val, &t1, sizeof(t1));
+    else if (!*str2dec(s, t2, scale))
+        std::memcpy(val, &t2, sizeof(t2));
+    else
+        throw soci_error("Could not parse decimal value.");
+    to_isc<IntType>(val, var, scale);
+}
+
+template<typename IntType>
+std::string format_decimal(const void *sqldata, int sqlscale)
+{
+    IntType x = *reinterpret_cast<const IntType *>(sqldata);
+    std::stringstream out;
+    out << x;
+    std::string r = out.str();
+    if (sqlscale < 0)
+    {
+        if (static_cast<int>(r.size()) - (x < 0) <= -sqlscale)
+        {
+            r = std::string(size_t(x < 0), '-') +
+                std::string(-sqlscale - (r.size() - (x < 0)) + 1, '0') +
+                r.substr(size_t(x < 0), std::string::npos);
+        }
+        return r.substr(0, r.size() + sqlscale) + '.' +
+            r.substr(r.size() + sqlscale, std::string::npos);
+    }
+    return r + std::string(sqlscale, '0');
+}
+
+
+template<bool cond> struct cond_from_isc {};
+template<> struct cond_from_isc<true> {
+    static void checkInteger(short scale)
+    {
+        std::ostringstream msg;
+        msg << "Can't convert value with scale " << -scale
+            << " to integral type";
+        throw soci_error(msg.str());
+    }
+};
+template<> struct cond_from_isc<false>
+{
+    static void checkInteger(short scale) { SOCI_UNUSED(scale) }
+};
+
+template<typename T1>
+T1 from_isc(XSQLVAR * var)
+{
+    short scale = var->sqlscale;
+    T1 tens = 1;
+
+    if (scale < 0)
+    {
+        cond_from_isc<std::numeric_limits<T1>::is_integer>::checkInteger(scale);
+        for (int i = 0; i > scale; --i)
+        {
+            tens *= 10;
+        }
+    }
+
+    SOCI_GCC_WARNING_SUPPRESS(cast-align)
+
+    switch (var->sqltype & ~1)
+    {
+    case SQL_SHORT:
+        return static_cast<T1>(*reinterpret_cast<int16_t*>(var->sqldata)/tens);
+    case SQL_LONG:
+        return static_cast<T1>(*reinterpret_cast<int32_t*>(var->sqldata)/tens);
+    case SQL_INT64:
+        return static_cast<T1>(*reinterpret_cast<int64_t*>(var->sqldata)/tens);
+    case SQL_FLOAT:
+        return static_cast<T1>(*reinterpret_cast<float*>(var->sqldata));
+    case SQL_DOUBLE:
+        return static_cast<T1>(*reinterpret_cast<double*>(var->sqldata));
+    default:
+        throw soci_error("Incorrect data type for numeric conversion");
+    }
+
+    SOCI_GCC_WARNING_RESTORE(cast-align)
+}
+
+} // namespace firebird
+
+} // namespace details
+
+} // namespace soci
+
+#endif // SOCI_FIREBIRD_COMMON_H_INCLUDED

+ 35 - 0
3rdparty/soci/include/private/firebird/error-firebird.h

@@ -0,0 +1,35 @@
+//
+// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, Rafal Bobrowski
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_FIREBIRD_ERROR_H_INCLUDED
+#define SOCI_FIREBIRD_ERROR_H_INCLUDED
+
+#include "soci/firebird/soci-firebird.h"
+#include <string>
+
+namespace soci
+{
+
+namespace details
+{
+
+namespace firebird
+{
+
+void SOCI_FIREBIRD_DECL get_iscerror_details(ISC_STATUS * status_vector, std::string &msg);
+
+bool SOCI_FIREBIRD_DECL check_iscerror(ISC_STATUS const * status_vector, long errNum);
+
+void SOCI_FIREBIRD_DECL throw_iscerror(ISC_STATUS * status_vector);
+
+} // namespace firebird
+
+} // namespace details
+
+} // namespace soci
+
+#endif // SOCI_FIREBIRD_ERROR_H_INCLUDED

+ 42 - 0
3rdparty/soci/include/private/soci-autostatement.h

@@ -0,0 +1,42 @@
+//
+// Copyright (C) 2020 Vadim Zeitlin
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_PRIVATE_SOCI_AUTOSTATEMENT_H_INCLUDED
+#define SOCI_PRIVATE_SOCI_AUTOSTATEMENT_H_INCLUDED
+
+namespace soci
+{
+
+namespace details
+{
+
+// This helper class can be used with any statement backend to initialize and
+// cleanup a statement backend object in a RAII way. Normally this is not
+// needed because it's done by statement_impl, but this can be handy when using
+// a concrete backend inside this backend own code, see e.g. ODBC session
+// implementation.
+template <typename Backend>
+struct auto_statement : Backend
+{
+    template <typename Session>
+    explicit auto_statement(Session& session)
+        : Backend(session)
+    {
+        this->alloc();
+    }
+
+    ~auto_statement() override
+    {
+        this->clean_up();
+    }
+};
+
+} // namespace details
+
+} // namespace soci
+
+#endif // SOCI_PRIVATE_SOCI_AUTOSTATEMENT_H_INCLUDED

+ 39 - 0
3rdparty/soci/include/private/soci-compiler.h

@@ -0,0 +1,39 @@
+//
+// Copyright (C) 2015 Vadim Zeitlin
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_PRIVATE_SOCI_COMPILER_H_INCLUDED
+#define SOCI_PRIVATE_SOCI_COMPILER_H_INCLUDED
+
+#include "soci-cpp.h"
+
+// SOCI_CHECK_GCC(major,minor) evaluates to 1 when using g++ of at least this
+// version or 0 when using g++ of lesser version or not using g++ at all.
+#if defined(__GNUC__) && defined(__GNUC_MINOR__)
+#   define SOCI_CHECK_GCC(major, minor) \
+        ((__GNUC__ > (major)) \
+            || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
+#else
+#   define SOCI_CHECK_GCC(major, minor) 0
+#endif
+
+// GCC_WARNING_{SUPPRESS,RESTORE} macros can be used to bracket the code
+// producing a specific warning to disable it.
+//
+// They only work with g++ 4.6+ or clang, warnings are not disabled for earlier
+// g++ versions.
+#if defined(__clang__) || SOCI_CHECK_GCC(4, 6)
+#   define SOCI_GCC_WARNING_SUPPRESS(x) \
+        _Pragma (SOCI_STRINGIZE(GCC diagnostic push)) \
+        _Pragma (SOCI_STRINGIZE(GCC diagnostic ignored SOCI_STRINGIZE(SOCI_CONCAT(-W,x))))
+#   define SOCI_GCC_WARNING_RESTORE(x) \
+        _Pragma (SOCI_STRINGIZE(GCC diagnostic pop))
+#else /* gcc < 4.6 or not gcc and not clang at all */
+#   define SOCI_GCC_WARNING_SUPPRESS(x)
+#   define SOCI_GCC_WARNING_RESTORE(x)
+#endif
+
+#endif // SOCI_PRIVATE_SOCI_COMPILER_H_INCLUDED

+ 30 - 0
3rdparty/soci/include/private/soci-cpp.h

@@ -0,0 +1,30 @@
+//
+// Copyright (C) 2015 Vadim Zeitlin
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_PRIVATE_SOCI_CPP_H_INCLUDED
+#define SOCI_PRIVATE_SOCI_CPP_H_INCLUDED
+
+// Some very common preprocessor helpers.
+
+// SOCI_CONCAT() pastes together two tokens after expanding them.
+#define SOCI_CONCAT_IMPL(x, y) x ## y
+#define SOCI_CONCAT(x, y) SOCI_CONCAT_IMPL(x, y)
+
+// SOCI_STRINGIZE() makes a string of its argument after expanding it.
+#define SOCI_STRINGIZE_IMPL(x) #x
+#define SOCI_STRINGIZE(x) SOCI_STRINGIZE_IMPL(x)
+
+// SOCI_MAKE_UNIQUE_NAME() creates a uniquely named identifier with the given
+// prefix.
+//
+// It uses __COUNTER__ macro to avoid problems with broken __LINE__ in MSVC
+// when using "Edit and Continue" (/ZI) option as there are no compilers known
+// to work with SOCI and not support it. If one such is ever discovered, we
+// should use __LINE__ for it instead.
+#define SOCI_MAKE_UNIQUE_NAME(name) SOCI_CONCAT(name, __COUNTER__)
+
+#endif // SOCI_PRIVATE_SOCI_CPP_H_INCLUDED

+ 80 - 0
3rdparty/soci/include/private/soci-cstrtod.h

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

+ 87 - 0
3rdparty/soci/include/private/soci-cstrtoi.h

@@ -0,0 +1,87 @@
+//
+// Copyright (C) 2020 Vadim Zeitlin.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_PRIVATE_SOCI_CSTRTOI_H_INCLUDED
+#define SOCI_PRIVATE_SOCI_CSTRTOI_H_INCLUDED
+
+#include "soci/error.h"
+
+#include <cstdlib>
+#include <limits>
+
+namespace soci
+{
+
+namespace details
+{
+
+// Convert string to a signed value of the given type, checking for overflow.
+//
+// Fill the provided result parameter and return true on success or false on
+// error, e.g. if the string couldn't be converted at all, if anything remains
+// in the string after conversion or if the value is out of range.
+template <typename T>
+bool cstring_to_integer(T& result, char const* buf)
+{
+    char * end;
+
+    // No strtoll() on MSVC versions prior to Visual Studio 2013
+#if !defined (_MSC_VER) || (_MSC_VER >= 1800)
+    long long t = strtoll(buf, &end, 10);
+#else
+    long long t = _strtoi64(buf, &end, 10);
+#endif
+
+    if (end == buf || *end != '\0')
+        return false;
+
+    // successfully converted to long long
+    // and no other characters were found in the buffer
+
+    const T max = (std::numeric_limits<T>::max)();
+    const T min = (std::numeric_limits<T>::min)();
+    if (t > static_cast<long long>(max) || t < static_cast<long long>(min))
+        return false;
+
+    result = static_cast<T>(t);
+
+    return true;
+}
+
+// Similar to the above, but for the unsigned integral types.
+template <typename T>
+bool cstring_to_unsigned(T& result, char const* buf)
+{
+    char * end;
+
+    // No strtoll() on MSVC versions prior to Visual Studio 2013
+#if !defined (_MSC_VER) || (_MSC_VER >= 1800)
+    unsigned long long t = strtoull(buf, &end, 10);
+#else
+    unsigned long long t = _strtoui64(buf, &end, 10);
+#endif
+
+    if (end == buf || *end != '\0')
+        return false;
+
+    // successfully converted to unsigned long long
+    // and no other characters were found in the buffer
+
+    const T max = (std::numeric_limits<T>::max)();
+    if (t > static_cast<unsigned long long>(max))
+        return false;
+
+    result = static_cast<T>(t);
+
+    return true;
+}
+
+} // namespace details
+
+} // namespace soci
+
+#endif // SOCI_PRIVATE_SOCI_CSTRTOI_H_INCLUDED

+ 58 - 0
3rdparty/soci/include/private/soci-dtocstr.h

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

+ 129 - 0
3rdparty/soci/include/private/soci-exchange-cast.h

@@ -0,0 +1,129 @@
+//
+// Copyright (C) 2015 Vadim Zeitlin
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_EXCHANGE_CAST_H_INCLUDED
+#define SOCI_EXCHANGE_CAST_H_INCLUDED
+
+#include "soci/soci-backend.h"
+#include "soci/type-wrappers.h"
+#include "soci/blob.h"
+
+#include <cstdint>
+#include <ctime>
+
+namespace soci
+{
+
+namespace details
+{
+
+// cast the given non-null untyped pointer to its corresponding type
+template <exchange_type e> struct exchange_type_traits;
+
+template <>
+struct exchange_type_traits<x_char>
+{
+  typedef char value_type;
+};
+
+template <>
+struct exchange_type_traits<x_stdstring>
+{
+  typedef std::string value_type;
+};
+
+template <>
+struct exchange_type_traits<x_int8>
+{
+  typedef int8_t value_type;
+};
+
+template <>
+struct exchange_type_traits<x_uint8>
+{
+  typedef uint8_t value_type;
+};
+
+template <>
+struct exchange_type_traits<x_int16>
+{
+  typedef int16_t value_type;
+};
+
+template <>
+struct exchange_type_traits<x_uint16>
+{
+  typedef uint16_t value_type;
+};
+
+template <>
+struct exchange_type_traits<x_int32>
+{
+  typedef int32_t value_type;
+};
+
+template <>
+struct exchange_type_traits<x_uint32>
+{
+  typedef uint32_t value_type;
+};
+
+template <>
+struct exchange_type_traits<x_int64>
+{
+  typedef int64_t value_type;
+};
+
+template <>
+struct exchange_type_traits<x_uint64>
+{
+  typedef uint64_t value_type;
+};
+
+template <>
+struct exchange_type_traits<x_double>
+{
+  typedef double value_type;
+};
+
+template <>
+struct exchange_type_traits<x_stdtm>
+{
+  typedef std::tm value_type;
+};
+
+template <>
+struct exchange_type_traits<x_longstring>
+{
+  typedef long_string value_type;
+};
+
+template <>
+struct exchange_type_traits<x_xmltype>
+{
+  typedef xml_type value_type;
+};
+
+template <>
+struct exchange_type_traits<x_blob>
+{
+  typedef blob value_type;
+};
+
+// exchange_type_traits not defined for x_statement, x_rowid and x_blob here.
+
+template <exchange_type e>
+typename exchange_type_traits<e>::value_type& exchange_type_cast(void *data)
+{
+    return *static_cast<typename exchange_type_traits<e>::value_type*>(data);
+}
+
+} // namespace details
+
+} // namespace soci
+
+#endif // SOCI_EXCHANGE_CAST_H_INCLUDED

+ 69 - 0
3rdparty/soci/include/private/soci-mktime.h

@@ -0,0 +1,69 @@
+//
+// Copyright (C) 2015 Vadim Zeitlin.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_PRIVATE_SOCI_MKTIME_H_INCLUDED
+#define SOCI_PRIVATE_SOCI_MKTIME_H_INCLUDED
+
+// Not <ctime> because we also want to get timegm() if available.
+#include <time.h>
+
+#ifdef _WIN32
+#define timegm _mkgmtime
+#endif
+
+namespace soci
+{
+
+namespace details
+{
+
+SOCI_DECL time_t timegm_impl_soci ( struct tm* tb );
+
+template <typename T>
+auto timegm_impl(T* t) -> decltype(timegm(t))
+{
+    return timegm(t);    
+}
+
+template <typename T>
+auto timegm_impl(T t) -> time_t
+{
+    return timegm_impl_soci(t);
+}
+
+// Fill the provided struct tm with the values corresponding to the given date
+// in UTC.
+//
+// Notice that both years and months are normal human 1-based values here and
+// not 1900 or 0-based as in struct tm itself.
+inline
+void
+mktime_from_ymdhms(tm& t,
+                   int year, int month, int day,
+                   int hour, int minute, int second)
+{
+    t.tm_isdst = -1;
+    t.tm_year = year - 1900;
+    t.tm_mon  = month - 1;
+    t.tm_mday = day;
+    t.tm_hour = hour;
+    t.tm_min  = minute;
+    t.tm_sec  = second;
+
+    timegm_impl(&t);
+}
+
+// Helper function for parsing datetime values.
+//
+// Throws if the string in buf couldn't be parsed as a date or a time string.
+SOCI_DECL void parse_std_tm(char const *buf, std::tm &t);
+
+} // namespace details
+
+} // namespace soci
+
+#endif // SOCI_PRIVATE_SOCI_MKTIME_H_INCLUDED

+ 82 - 0
3rdparty/soci/include/private/soci-trivial-blob-backend.h

@@ -0,0 +1,82 @@
+#ifndef SOCI_PRIVATE_SOCI_TRIVIAL_BLOB_BACKEND_H_INCLUDED
+#define SOCI_PRIVATE_SOCI_TRIVIAL_BLOB_BACKEND_H_INCLUDED
+
+#include "soci/soci-backend.h"
+
+#include <vector>
+#include <cstring>
+#include <cstdint>
+
+namespace soci
+{
+
+namespace details
+{
+
+/**
+ * This Blob implementation uses an explicit buffer that is read from and written to, instead of
+ * directly communicating with the underlying database.
+ * Thus, it is intended to be used whenever the underlying database does not offer a more efficient
+ * way of dealing with BLOBs.
+ */
+class trivial_blob_backend : public details::blob_backend
+{
+public:
+    std::size_t get_len() override { return buffer_.size(); }
+
+    std::size_t read_from_start(void* buf, std::size_t toRead,
+        std::size_t offset = 0) override
+    {
+        if (offset > buffer_.size() || (offset ==  buffer_.size() && offset > 0))
+        {
+            throw soci_error("Can't read past-the-end of BLOB data.");
+        }
+
+        // make sure that we don't try to read
+        // past the end of the data
+        toRead = std::min<decltype(toRead)>(toRead, buffer_.size() - offset);
+
+        memcpy(buf, buffer_.data() + offset, toRead);
+
+        return toRead;
+    }
+
+    std::size_t write_from_start(const void* buf, std::size_t toWrite,
+        std::size_t offset = 0) override
+    {
+        if (offset > buffer_.size())
+        {
+            throw soci_error("Can't start writing far past-the-end of BLOB data.");
+        }
+
+        buffer_.resize(std::max<std::size_t>(buffer_.size(), offset + toWrite));
+
+        memcpy(buffer_.data() + offset, buf, toWrite);
+
+        return toWrite;
+    }
+
+    std::size_t append(void const* buf, std::size_t toWrite) override
+    {
+        return write_from_start(buf, toWrite, buffer_.size());
+    }
+
+    void trim(std::size_t newLen) override { buffer_.resize(newLen); }
+
+    std::size_t set_data(void const* buf, std::size_t toWrite)
+    {
+        buffer_.clear();
+        return write_from_start(buf, toWrite);
+    }
+
+    const std::uint8_t *get_buffer() const { return buffer_.data(); }
+
+protected:
+    std::vector< std::uint8_t > buffer_;
+};
+
+}
+
+}
+
+#endif // SOCI_PRIVATE_SOCI_TRIVIAL_BLOB_BACKEND_H_INCLUDED

+ 157 - 0
3rdparty/soci/include/private/soci-vector-helpers.h

@@ -0,0 +1,157 @@
+//
+// Copyright (C) 2021 Sinitsyn Ilya
+// 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_VECTOR_HELPERS_H_INCLUDED
+#define SOCI_VECTOR_HELPERS_H_INCLUDED
+
+#include "soci-exchange-cast.h"
+
+namespace soci
+{
+
+namespace details
+{
+
+// Helper functions to work with vectors.
+
+template <exchange_type e>
+std::vector<typename exchange_type_traits<e>::value_type>& exchange_vector_type_cast(void *data)
+{
+    return *static_cast<std::vector<typename exchange_type_traits<e>::value_type>*>(data);
+}
+
+// Get the size of the vector.
+inline std::size_t get_vector_size(exchange_type e, void *data)
+{
+    switch (e)
+    {
+        case x_char:
+            return exchange_vector_type_cast<x_char>(data).size();
+        case x_stdstring:
+            return exchange_vector_type_cast<x_stdstring>(data).size();
+        case x_int8:
+            return exchange_vector_type_cast<x_int8>(data).size();
+        case x_uint8:
+            return exchange_vector_type_cast<x_uint8>(data).size();
+        case x_int16:
+            return exchange_vector_type_cast<x_int16>(data).size();
+        case x_uint16:
+            return exchange_vector_type_cast<x_uint16>(data).size();
+        case x_int32:
+            return exchange_vector_type_cast<x_int32>(data).size();
+        case x_uint32:
+            return exchange_vector_type_cast<x_uint32>(data).size();
+        case x_int64:
+            return exchange_vector_type_cast<x_int64>(data).size();
+        case x_uint64:
+            return exchange_vector_type_cast<x_uint64>(data).size();
+        case x_double:
+            return exchange_vector_type_cast<x_double>(data).size();
+        case x_stdtm:
+            return exchange_vector_type_cast<x_stdtm>(data).size();
+        case x_xmltype:
+            return exchange_vector_type_cast<x_xmltype>(data).size();
+        case x_longstring:
+            return exchange_vector_type_cast<x_longstring>(data).size();
+        case x_statement:
+        case x_rowid:
+        case x_blob:
+            break;
+    }
+    throw soci_error("Failed to get the size of the vector of non-supported type.");
+}
+
+// Set the size of the vector.
+inline void resize_vector(exchange_type e, void *data, std::size_t newSize)
+{
+    switch (e)
+    {
+        case x_char:
+            exchange_vector_type_cast<x_char>(data).resize(newSize);
+            return;
+        case x_stdstring:
+            exchange_vector_type_cast<x_stdstring>(data).resize(newSize);
+            return;
+        case x_int8:
+            exchange_vector_type_cast<x_int8>(data).resize(newSize);
+            return;
+        case x_uint8:
+            exchange_vector_type_cast<x_uint8>(data).resize(newSize);
+            return;
+        case x_int16:
+            exchange_vector_type_cast<x_int16>(data).resize(newSize);
+            return;
+        case x_uint16:
+            exchange_vector_type_cast<x_uint16>(data).resize(newSize);
+            return;
+        case x_int32:
+            exchange_vector_type_cast<x_int32>(data).resize(newSize);
+            return;
+        case x_uint32:
+            exchange_vector_type_cast<x_uint32>(data).resize(newSize);
+            return;
+        case x_int64:
+            exchange_vector_type_cast<x_int64>(data).resize(newSize);
+            return;
+        case x_uint64:
+            exchange_vector_type_cast<x_uint64>(data).resize(newSize);
+            return;
+        case x_double:
+            exchange_vector_type_cast<x_double>(data).resize(newSize);
+            return;
+        case x_stdtm:
+            exchange_vector_type_cast<x_stdtm>(data).resize(newSize);
+            return;
+        case x_xmltype:
+            exchange_vector_type_cast<x_xmltype>(data).resize(newSize);
+            return;
+        case x_longstring:
+            exchange_vector_type_cast<x_longstring>(data).resize(newSize);
+            return;
+        case x_statement:
+        case x_rowid:
+        case x_blob:
+            break;
+    }
+    throw soci_error("Failed to get the size of the vector of non-supported type.");
+}
+
+// Get the string at the given index of the vector.
+inline std::string& vector_string_value(exchange_type e, void *data, std::size_t ind)
+{
+    switch (e)
+    {
+        case x_stdstring:
+            return exchange_vector_type_cast<x_stdstring>(data).at(ind);
+        case x_xmltype:
+            return exchange_vector_type_cast<x_xmltype>(data).at(ind).value;
+        case x_longstring:
+            return exchange_vector_type_cast<x_longstring>(data).at(ind).value;
+        case x_char:
+        case x_int8:
+        case x_uint8:
+        case x_int16:
+        case x_uint16:
+        case x_int32:
+        case x_uint32:
+        case x_int64:
+        case x_uint64:
+        case x_double:
+        case x_stdtm:
+        case x_statement:
+        case x_rowid:
+        case x_blob:
+            break;
+    }
+    throw soci_error("Can't get the string value from the vector of values with non-supported type.");
+}
+
+} // namespace details
+
+} // namespace soci
+
+#endif // SOCI_VECTOR_HELPERS_H_INCLUDED

+ 40 - 0
3rdparty/soci/include/soci/backend-loader.h

@@ -0,0 +1,40 @@
+//
+// Copyright (C) 2008 Maciej Sobczak with contributions from Artyom Tonkikh
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_BACKEND_LOADER_H_INCLUDED
+#define SOCI_BACKEND_LOADER_H_INCLUDED
+
+#include "soci/soci-backend.h"
+// std
+#include <string>
+#include <vector>
+
+namespace soci
+{
+
+namespace dynamic_backends
+{
+
+// only used internally and shouldn't/can't be used from outside the library,
+// successful calls to get() should be matched by calls to unget() with the
+// same name
+backend_factory const & get(std::string const & name);
+void unget(std::string const & name);
+
+// provided for advanced user-level management
+SOCI_DECL std::vector<std::string> & search_paths();
+SOCI_DECL void register_backend(std::string const & name, std::string const & shared_object = std::string());
+SOCI_DECL void register_backend(std::string const & name, backend_factory const & factory);
+SOCI_DECL std::vector<std::string> list_all();
+SOCI_DECL void unload(std::string const & name);
+SOCI_DECL void unload_all();
+
+} // namespace dynamic_backends
+
+} // namespace soci
+
+#endif // SOCI_BACKEND_LOADER_H_INCLUDED

+ 216 - 0
3rdparty/soci/include/soci/bind-values.h

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

+ 59 - 0
3rdparty/soci/include/soci/blob-exchange.h

@@ -0,0 +1,59 @@
+//
+// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_BLOB_EXCHANGE_H_INCLUDED
+#define SOCI_BLOB_EXCHANGE_H_INCLUDED
+
+#include "soci/blob.h"
+#include "soci/into-type.h"
+#include "soci/use-type.h"
+// std
+#include <string>
+
+namespace soci
+{
+
+namespace details
+{
+
+template <>
+class into_type<blob> : public standard_into_type
+{
+public:
+    into_type(blob & b) : standard_into_type(&b, x_blob) {}
+    into_type(blob & b, indicator & ind)
+        : standard_into_type(&b, x_blob, ind) {}
+};
+
+template <>
+class use_type<blob> : public standard_use_type
+{
+public:
+    use_type(blob & b, std::string const & name = std::string())
+        : standard_use_type(&b, x_blob, false, name) {}
+    use_type(blob const & b, std::string const & name = std::string())
+        : standard_use_type(const_cast<blob *>(&b), x_blob, true, name) {}
+    use_type(blob & b, indicator & ind,
+        std::string const & name = std::string())
+        : standard_use_type(&b, x_blob, ind, false, name) {}
+    use_type(blob const & b, indicator & ind,
+        std::string const & name = std::string())
+        : standard_use_type(const_cast<blob *>(&b), x_blob, ind, true, name) {}
+};
+
+template <>
+struct exchange_traits<soci::blob>
+{
+    typedef basic_type_tag type_family;
+    enum { x_type = x_blob };
+};
+
+} // namespace details
+
+} // namespace soci
+
+#endif // SOCI_BLOB_EXCHANGE_H_INCLUDED

+ 84 - 0
3rdparty/soci/include/soci/blob.h

@@ -0,0 +1,84 @@
+//
+// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_BLOB_H_INCLUDED
+#define SOCI_BLOB_H_INCLUDED
+
+#include "soci/soci-platform.h"
+// std
+#include <cstddef>
+#include <memory>
+
+namespace soci
+{
+// basic blob operations
+
+class session;
+
+namespace details
+{
+class blob_backend;
+} // namespace details
+
+class SOCI_DECL blob
+{
+public:
+    // Creates an invalid blob object
+    blob() = default;
+    explicit blob(session & s);
+    ~blob();
+
+    blob(blob &&other) = default;
+    blob &operator=(blob &&other) = default;
+
+    // Checks whether this blob is in a valid state
+    bool is_valid() const;
+
+    // (Re)initializes this blob
+    void initialize(session &s);
+
+    std::size_t get_len();
+
+    // offset is backend-specific
+    [[deprecated("Use read_from_start instead")]]
+    std::size_t read(std::size_t offset, void * buf, std::size_t toRead);
+
+    // Extracts data from this blob into the given buffer.
+    // At most toRead bytes are extracted (and copied into buf).
+    // The amount of actually read bytes is returned.
+    //
+    // Note: Using an offset > 0 on a blob whose size is less than
+    // or equal to offset, will throw an exception.
+    std::size_t read_from_start(void * buf, std::size_t toRead,
+        std::size_t offset = 0);
+
+    // offset is backend-specific
+    [[deprecated("Use write_from_start instead")]]
+    std::size_t write(std::size_t offset, const void * buf,
+        std::size_t toWrite);
+
+    // offset starts from 0
+    std::size_t write_from_start(const void * buf, std::size_t toWrite,
+        std::size_t offset = 0);
+
+    std::size_t append(const void * buf, std::size_t toWrite);
+
+    void trim(std::size_t newLen);
+
+    details::blob_backend * get_backend() { return backEnd_.get(); }
+
+private:
+    SOCI_NOT_COPYABLE(blob)
+
+    std::unique_ptr<details::blob_backend> backEnd_;
+
+    void ensure_initialized();
+};
+
+} // namespace soci
+
+#endif

+ 28 - 0
3rdparty/soci/include/soci/boost-fusion.h

@@ -0,0 +1,28 @@
+//
+// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_BOOST_FUSION_H_INCLUDED
+#define SOCI_BOOST_FUSION_H_INCLUDED
+
+#ifndef SOCI_MAX_FUSION_SEQUENCE_LENGTH
+#define SOCI_MAX_FUSION_SEQUENCE_LENGTH 10
+#endif
+
+#include "values.h"
+#include "type-conversion-traits.h"
+// boost
+#include <boost/fusion/container/vector.hpp>
+#include <boost/fusion/sequence/intrinsic/at.hpp>
+#include <boost/fusion/sequence/intrinsic/size.hpp>
+#include <boost/fusion/include/at.hpp>
+#include <boost/fusion/support/is_sequence.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+#include <boost/utility/enable_if.hpp>
+
+
+#endif // SOCI_BOOST_FUSION_H_INCLUDED

+ 50 - 0
3rdparty/soci/include/soci/boost-gregorian-date.h

@@ -0,0 +1,50 @@
+//
+// Copyright (C) 2008 Maciej Sobczak
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_BOOST_GREGORIAN_DATE_H_INCLUDED
+#define SOCI_BOOST_GREGORIAN_DATE_H_INCLUDED
+
+#include "soci/type-conversion-traits.h"
+// boost
+#include <boost/date_time/gregorian/gregorian_types.hpp>
+#include <boost/date_time/gregorian/conversion.hpp>
+// std
+#include <ctime>
+
+namespace soci
+{
+
+template<>
+struct type_conversion<boost::gregorian::date>
+{
+    typedef std::tm base_type;
+
+    static void from_base(
+        base_type const & in, indicator ind, boost::gregorian::date & out)
+    {
+        if (ind == i_null)
+        {
+            throw soci_error("Null value not allowed for this type");
+        }
+
+        out = boost::gregorian::date_from_tm(in);
+    }
+
+    struct move_from_base_check :
+        std::integral_constant<bool, false> {};
+
+    static void to_base(
+        boost::gregorian::date const & in, base_type & out, indicator & ind)
+    {
+        out = boost::gregorian::to_tm(in);
+        ind = i_ok;
+    }
+};
+
+} // namespace soci
+
+#endif // SOCI_BOOST_GREGORIAN_DATE_H_INCLUDED

+ 92 - 0
3rdparty/soci/include/soci/boost-optional.h

@@ -0,0 +1,92 @@
+//
+// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_BOOST_OPTIONAL_H_INCLUDED
+#define SOCI_BOOST_OPTIONAL_H_INCLUDED
+
+#include "soci/type-conversion-traits.h"
+// boost
+#include <boost/optional.hpp>
+#include <boost/optional/optional_io.hpp>
+
+namespace soci
+{
+
+// simple fall-back for boost::optional
+template <typename T>
+struct type_conversion<boost::optional<T> >
+{
+    typedef typename type_conversion<T>::base_type base_type;
+
+    struct from_base_check : std::integral_constant<bool, true> {};
+
+    static void from_base(base_type const & in, indicator ind,
+        boost::optional<T> & out)
+    {
+        if (ind == i_null)
+        {
+            out.reset();
+        }
+        else
+        {
+            T tmp = T();
+            type_conversion<T>::from_base(in, ind, tmp);
+            out = tmp;
+        }
+    }
+
+    struct move_from_base_check :
+        std::integral_constant<bool,
+            !std::is_const<base_type>::value
+            && std::is_constructible<boost::optional<T>, typename std::add_rvalue_reference<base_type>::type>::value
+        > {};
+
+
+    static void move_from_base(base_type & in, indicator ind, boost::optional<T> & out)
+    {
+        static_assert(move_from_base_check::value,
+                "move_to_base can only be used if the target type can be constructed from an rvalue base reference");
+        if (ind == i_null)
+        {
+            out.reset();
+        }
+        else
+        {
+            out = std::move(in);
+        }
+    }
+
+    static void to_base(boost::optional<T> const & in,
+        base_type & out, indicator & ind)
+    {
+        if (in.is_initialized())
+        {
+            type_conversion<T>::to_base(in.get(), out, ind);
+        }
+        else
+        {
+            ind = i_null;
+        }
+    }
+
+    static void move_to_base(boost::optional<T> & in, base_type & out, indicator & ind)
+    {
+        if (in.is_initialized())
+        {
+            out = std::move(in.get());
+            ind = i_ok;
+        }
+        else
+        {
+            ind = i_null;
+        }
+    }
+};
+
+} // namespace soci
+
+#endif // SOCI_BOOST_OPTIONAL_H_INCLUDED

+ 18 - 0
3rdparty/soci/include/soci/boost-tuple.h

@@ -0,0 +1,18 @@
+//
+// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_BOOST_TUPLE_H_INCLUDED
+#define SOCI_BOOST_TUPLE_H_INCLUDED
+
+#include "values.h"
+#include "type-conversion-traits.h"
+
+// boost
+#include <boost/tuple/tuple.hpp>
+#include <boost/fusion/adapted/boost_tuple.hpp>
+
+#endif // SOCI_BOOST_TUPLE_H_INCLUDED

+ 47 - 0
3rdparty/soci/include/soci/callbacks.h

@@ -0,0 +1,47 @@
+//
+// Copyright (C) 2015 Maciej Sobczak
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_CALLBACKS_H_INCLUDED
+#define SOCI_CALLBACKS_H_INCLUDED
+
+namespace soci
+{
+
+class session;
+
+// Simple callback interface for reporting failover events.
+// The meaning of each operation is intended to be portable,
+// but the behaviour details and parameters can be backend-specific.
+class SOCI_DECL failover_callback
+{
+public:
+
+    // Called when the failover operation has started,
+    // after discovering connectivity problems.
+    virtual void started() {}
+
+    // Called after successful failover and creating a new connection;
+    // the sql parameter denotes the new connection and allows the user
+    // to replay any initial sequence of commands (like session configuration).
+    virtual void finished(session & /* sql */) {}
+
+    // Called when the attempt to reconnect failed,
+    // if the user code sets the retry parameter to true,
+    // then new connection will be attempted;
+    // the newTarget connection string is a hint that can be ignored
+    // by external means.
+    virtual void failed(bool & /* out */ /* retry */,
+        std::string & /* out */ /* newTarget */) {}
+
+    // Called when there was a failure that prevents further failover attempts.
+    virtual void aborted() {}
+};
+
+} // namespace soci
+
+#endif // SOCI_CALLBACKS_H_INCLUDED
+

+ 149 - 0
3rdparty/soci/include/soci/column-info.h

@@ -0,0 +1,149 @@
+//
+// Copyright (C) 2016 Maciej Sobczak
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_COLUMN_INFO_H_INCLUDED
+#define SOCI_COLUMN_INFO_H_INCLUDED
+
+#include "soci/soci-backend.h"
+#include "soci/type-conversion.h"
+#include "soci/values.h"
+
+#include <cstdint>
+
+namespace soci
+{
+
+struct SOCI_DECL column_info
+{
+    std::string name;
+    // DEPRECATED. USE dataType INSTEAD.
+    data_type type;
+    db_type dataType;
+    std::size_t length; // meaningful for text columns only
+    std::size_t precision;
+    std::size_t scale;
+    bool nullable;
+};
+
+template <>
+struct type_conversion<column_info>
+{
+    typedef values base_type;
+
+    static std::size_t get_numeric_value(const values & v,
+        const std::string & field_name)
+    {
+        db_type dt = v.get_properties(field_name).get_db_type();
+        switch (dt)
+        {
+        case db_double:
+            return static_cast<std::size_t>(
+                v.get<double>(field_name, 0.0));
+        case db_int8:
+            return static_cast<std::size_t>(
+                v.get<int8_t>(field_name, 0));
+        case db_uint8:
+            return static_cast<std::size_t>(
+                v.get<uint8_t>(field_name, 0));
+        case db_int16:
+            return static_cast<std::size_t>(
+                v.get<int16_t>(field_name, 0));
+        case db_uint16:
+            return static_cast<std::size_t>(
+                v.get<uint16_t>(field_name, 0));
+        case db_int32:
+            return static_cast<std::size_t>(
+                v.get<int32_t>(field_name, 0));
+        case db_uint32:
+            return static_cast<std::size_t>(
+                v.get<uint32_t>(field_name, 0));
+        case db_int64:
+            return static_cast<std::size_t>(
+                v.get<int64_t>(field_name, 0ll));
+        case db_uint64:
+            return static_cast<std::size_t>(
+                v.get<uint64_t>(field_name, 0ull));
+        default:
+            return 0u;
+        }
+    }
+
+    static void from_base(values const & v, indicator /* ind */, column_info & ci)
+    {
+        ci.name = v.get<std::string>("COLUMN_NAME");
+
+        ci.length = get_numeric_value(v, "CHARACTER_MAXIMUM_LENGTH");
+        ci.precision = get_numeric_value(v, "NUMERIC_PRECISION");
+        ci.scale = get_numeric_value(v, "NUMERIC_SCALE");
+
+        const std::string & type_name = v.get<std::string>("DATA_TYPE");
+        if (type_name == "text" || type_name == "TEXT" ||
+            type_name == "clob" || type_name == "CLOB" ||
+            type_name.find("char") != std::string::npos ||
+            type_name.find("CHAR") != std::string::npos)
+        {
+            ci.type = dt_string;
+            ci.dataType = db_string;
+        }
+        else if (type_name == "integer" || type_name == "INTEGER")
+        {
+            ci.type = dt_integer;
+            ci.dataType = db_int32;
+        }
+        else if (type_name.find("number") != std::string::npos ||
+            type_name.find("NUMBER") != std::string::npos ||
+            type_name.find("numeric") != std::string::npos ||
+            type_name.find("NUMERIC") != std::string::npos)
+        {
+            if (ci.scale != 0)
+            {
+                ci.type = dt_double;
+                ci.dataType = db_double;
+            }
+            else
+            {
+                ci.type = dt_integer;
+                ci.dataType = db_int32;
+            }
+        }
+        else if (type_name.find("time") != std::string::npos ||
+            type_name.find("TIME") != std::string::npos ||
+            type_name.find("date") != std::string::npos ||
+            type_name.find("DATE") != std::string::npos)
+        {
+            ci.type = dt_date;
+            ci.dataType = db_date;
+        }
+        else if (type_name.find("blob") != std::string::npos ||
+            type_name.find("BLOB") != std::string::npos ||
+            type_name.find("oid") != std::string::npos ||
+            type_name.find("OID") != std::string::npos)
+        {
+            ci.type = dt_blob;
+            ci.dataType = db_blob;
+        }
+        else if (type_name.find("xml") != std::string::npos ||
+            type_name.find("XML") != std::string::npos)
+        {
+            ci.type = dt_xml;
+            ci.dataType = db_xml;
+        }
+        else
+        {
+            // this seems to be a safe default
+            ci.type = dt_string;
+            ci.dataType = db_string;
+        }
+
+        const std::string & nullable_s = v.get<std::string>("IS_NULLABLE");
+        ci.nullable = (nullable_s == "YES");
+    }
+};
+
+} // namespace soci
+
+#endif // SOCI_COLUMN_INFO_H_INCLUDED

+ 99 - 0
3rdparty/soci/include/soci/connection-parameters.h

@@ -0,0 +1,99 @@
+//
+// Copyright (C) 2013 Vadim Zeitlin
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_CONNECTION_PARAMETERS_H_INCLUDED
+#define SOCI_CONNECTION_PARAMETERS_H_INCLUDED
+
+#include "soci/soci-platform.h"
+
+#include <map>
+#include <string>
+
+namespace soci
+{
+
+// Names of some predefined options and their values.
+extern SOCI_DECL char const * option_reconnect;
+extern SOCI_DECL char const * option_true;
+
+namespace details
+{
+
+class dynamic_backend_ref;
+
+} // namespace details
+
+class backend_factory;
+
+// Simple container for the information used when opening a session.
+class SOCI_DECL connection_parameters
+{
+public:
+    connection_parameters();
+    connection_parameters(backend_factory const & factory, std::string const & connectString);
+    connection_parameters(std::string const & backendName, std::string const & connectString);
+    explicit connection_parameters(std::string const & fullConnectString);
+
+    connection_parameters(connection_parameters const& other);
+    connection_parameters(connection_parameters && other);
+    connection_parameters& operator=(connection_parameters const& other);
+    connection_parameters& operator=(connection_parameters && other);
+
+    ~connection_parameters();
+
+
+    // Retrieve the backend and the connection strings specified in the ctor.
+    backend_factory const * get_factory() const { return factory_; }
+    void set_connect_string(const std::string & connectString) { connectString_ = connectString; }
+    std::string const & get_connect_string() const { return connectString_; }
+
+    // Set the value of the given option, overwriting any previous value.
+    void set_option(const char * name, std::string const & value)
+    {
+        options_[name] = value;
+    }
+
+    // Return true if the option with the given name was found and fill the
+    // provided parameter with its value.
+    bool get_option(const char * name, std::string & value) const
+    {
+        Options::const_iterator const it = options_.find(name);
+        if (it == options_.end())
+            return false;
+
+        value = it->second;
+
+        return true;
+    }
+
+    // Return true if the option with the given name was found with option_true
+    // value.
+    bool is_option_on(const char * name) const
+    {
+      std::string value;
+      return get_option(name, value) && value == option_true;
+    }
+
+private:
+    void reset_after_move();
+
+    // The backend and connection string specified in our ctor.
+    backend_factory const * factory_;
+    std::string connectString_;
+
+    // References the backend name used for obtaining the factor from
+    // dynamic_backends.
+    details::dynamic_backend_ref * backendRef_;
+
+    // We store all the values as strings for simplicity.
+    typedef std::map<std::string, std::string> Options;
+    Options options_;
+};
+
+} // namespace soci
+
+#endif // SOCI_CONNECTION_PARAMETERS_H_INCLUDED

+ 41 - 0
3rdparty/soci/include/soci/connection-pool.h

@@ -0,0 +1,41 @@
+//
+// Copyright (C) 2008 Maciej Sobczak
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_CONNECTION_POOL_H_INCLUDED
+#define SOCI_CONNECTION_POOL_H_INCLUDED
+
+#include "soci/soci-platform.h"
+// std
+#include <cstddef>
+
+namespace soci
+{
+
+class session;
+
+class SOCI_DECL connection_pool
+{
+public:
+    explicit connection_pool(std::size_t size);
+    ~connection_pool();
+
+    session & at(std::size_t pos);
+
+    std::size_t lease();
+    bool try_lease(std::size_t & pos, int timeout);
+    void give_back(std::size_t pos);
+
+private:
+    struct connection_pool_impl;
+    connection_pool_impl * pimpl_;
+
+    SOCI_NOT_COPYABLE(connection_pool)
+};
+
+}
+
+#endif // SOCI_CONNECTION_POOL_H_INCLUDED

+ 293 - 0
3rdparty/soci/include/soci/db2/soci-db2.h

@@ -0,0 +1,293 @@
+//
+// Copyright (C) 2011-2013 Denis Chapligin
+// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_DB2_H_INCLUDED
+#define SOCI_DB2_H_INCLUDED
+
+#include <soci/soci-platform.h>
+
+#ifdef SOCI_DB2_SOURCE
+# define SOCI_DB2_DECL SOCI_DECL_EXPORT
+#else
+# define SOCI_DB2_DECL SOCI_DECL_IMPORT
+#endif
+
+#include <soci/soci-backend.h>
+
+#include <cstddef>
+#include <string>
+#include <vector>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <cstring>
+
+#include <sqlcli1.h>
+
+namespace soci
+{
+    namespace details { namespace db2
+    {
+        enum binding_method
+        {
+            BOUND_BY_NONE,
+            BOUND_BY_NAME,
+            BOUND_BY_POSITION
+        };
+
+        inline SQLPOINTER int_as_ptr(int n)
+        {
+            union
+            {
+                SQLPOINTER p;
+                int n;
+            } u;
+            u.n = n;
+            return u.p;
+        }
+    }}
+
+    static const std::size_t maxBuffer =  1024 * 1024 * 1024; //CLI limit is about 3 GB, but 1GB should be enough
+
+class SOCI_DB2_DECL db2_soci_error : public soci_error {
+public:
+    db2_soci_error(std::string const & msg, SQLRETURN rc) : soci_error(msg),errorCode(rc) {};
+    ~db2_soci_error() noexcept override { };
+
+    //We have to extract error information before exception throwing, cause CLI handles could be broken at the construction time
+    static const std::string sqlState(std::string const & msg,const SQLSMALLINT htype,const SQLHANDLE hndl);
+
+    SQLRETURN errorCode;
+};
+
+// 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;
+
+struct db2_statement_backend;
+
+struct SOCI_DB2_DECL db2_standard_into_type_backend : details::standard_into_type_backend
+{
+    db2_standard_into_type_backend(db2_statement_backend &st)
+        : statement_(st),buf(NULL)
+    {}
+
+    void define_by_pos(int& position, void* data, details::exchange_type type) override;
+
+    void pre_fetch() override;
+    void post_fetch(bool gotData, bool calledFromFetch, indicator* ind) override;
+
+    void clean_up() override;
+
+    db2_statement_backend& statement_;
+
+    char* buf;
+    void *data;
+    details::exchange_type type;
+    int position;
+    SQLSMALLINT cType;
+    SQLLEN valueLen;
+};
+
+struct SOCI_DB2_DECL db2_vector_into_type_backend : details::vector_into_type_backend
+{
+    db2_vector_into_type_backend(db2_statement_backend &st)
+        : statement_(st),buf(NULL)
+    {}
+
+    void define_by_pos(int& position, void* data, details::exchange_type type) override;
+
+    void pre_fetch() override;
+    void post_fetch(bool gotData, indicator* ind) override;
+
+    void resize(std::size_t sz) override;
+    std::size_t size() override;
+
+    void clean_up() override;
+
+    db2_statement_backend& statement_;
+
+    void prepare_indicators(std::size_t size);
+
+    std::vector<SQLLEN> indVec;
+    void *data;
+    char *buf;
+    int position_;
+    details::exchange_type type;
+    SQLSMALLINT cType;
+    std::size_t colSize;
+};
+
+struct SOCI_DB2_DECL db2_standard_use_type_backend : details::standard_use_type_backend
+{
+    db2_standard_use_type_backend(db2_statement_backend &st)
+        : statement_(st),buf(NULL),ind(0)
+    {}
+
+    void bind_by_pos(int& position, void* data, details::exchange_type type, bool readOnly) override;
+    void bind_by_name(std::string const& name, void* data, details::exchange_type type, bool readOnly) override;
+
+    void pre_use(indicator const* ind) override;
+    void post_use(bool gotData, indicator* ind) override;
+
+    void clean_up() override;
+
+    db2_statement_backend& statement_;
+
+    void *prepare_for_bind(SQLLEN &size, SQLSMALLINT &sqlType, SQLSMALLINT &cType);
+
+    void *data;
+    details::exchange_type type;
+    int position;
+    std::string name;
+    char* buf;
+    SQLLEN ind;
+};
+
+struct SOCI_DB2_DECL db2_vector_use_type_backend : details::vector_use_type_backend
+{
+    db2_vector_use_type_backend(db2_statement_backend &st)
+        : statement_(st),buf(NULL) {}
+
+    void bind_by_pos(int& position, void* data, details::exchange_type type) override;
+    void bind_by_name(std::string const& name, void* data, details::exchange_type type) override;
+
+    void pre_use(indicator const* ind) override;
+
+    std::size_t size() override;
+
+    void clean_up() override;
+
+    db2_statement_backend& statement_;
+
+    void prepare_indicators(std::size_t size);
+    void *prepare_for_bind(SQLUINTEGER &size,SQLSMALLINT &sqlType, SQLSMALLINT &cType);
+
+    std::vector<SQLLEN> indVec;
+    void *data;
+    char *buf;
+    details::exchange_type type;
+    std::size_t colSize;
+    int position;
+};
+
+struct db2_session_backend;
+struct SOCI_DB2_DECL db2_statement_backend : details::statement_backend
+{
+    db2_statement_backend(db2_session_backend &session);
+
+    void alloc() override;
+    void clean_up() override;
+    void prepare(std::string const& query, details::statement_type eType) override;
+
+    exec_fetch_result execute(int number) override;
+    exec_fetch_result fetch(int number) override;
+
+    long long get_affected_rows() override;
+    int get_number_of_rows() override;
+    std::string get_parameter_name(int index) const override;
+
+    std::string rewrite_for_procedure_call(std::string const& query) override;
+
+    int prepare_for_describe() override;
+    void describe_column(int colNum, db_type& dbtype, std::string& columnName) override;
+    size_t column_size(int col);
+
+    db2_standard_into_type_backend* make_into_type_backend() override;
+    db2_standard_use_type_backend* make_use_type_backend() override;
+    db2_vector_into_type_backend* make_vector_into_type_backend() override;
+    db2_vector_use_type_backend* make_vector_use_type_backend() override;
+
+    db2_session_backend& session_;
+
+    SQLHANDLE hStmt;
+    std::string query_;
+    std::vector<std::string> names_;
+    bool hasVectorUseElements;
+    SQLUINTEGER numRowsFetched;
+    details::db2::binding_method use_binding_method_;
+};
+
+struct db2_rowid_backend : details::rowid_backend
+{
+    db2_rowid_backend(db2_session_backend &session);
+
+    ~db2_rowid_backend() override;
+};
+
+struct db2_blob_backend : details::blob_backend
+{
+    db2_blob_backend(db2_session_backend& session);
+
+    ~db2_blob_backend() override;
+
+    std::size_t get_len() override;
+    std::size_t read_from_start(void* buf, std::size_t toRead, std::size_t offset = 0) override;
+    std::size_t write_from_start(const void* buf, std::size_t toWrite, std::size_t offset = 0) override;
+    std::size_t append(const void* buf, std::size_t toWrite) override;
+    void trim(std::size_t newLen) override;
+
+    db2_session_backend& session_;
+};
+
+struct db2_session_backend : details::session_backend
+{
+    db2_session_backend(connection_parameters const& parameters);
+
+    ~db2_session_backend() override;
+
+    bool is_connected() override;
+
+    void begin() override;
+    void commit() override;
+    void rollback() override;
+
+    std::string get_dummy_from_table() const override { return "sysibm.sysdummy1"; }
+
+    std::string get_backend_name() const override { return "DB2"; }
+
+    void clean_up();
+
+    db2_statement_backend* make_statement_backend() override;
+    db2_rowid_backend* make_rowid_backend() override;
+    db2_blob_backend* make_blob_backend() override;
+
+    void parseConnectString(std::string const &);
+    void parseKeyVal(std::string const &);
+
+    std::string connection_string_;
+    bool autocommit;
+    bool in_transaction;
+
+    SQLHANDLE hEnv; /* Environment handle */
+    SQLHANDLE hDbc; /* Connection handle */
+};
+
+struct SOCI_DB2_DECL db2_backend_factory : backend_factory
+{
+    db2_backend_factory() {}
+    db2_session_backend* make_session(
+        connection_parameters const & parameters) const override;
+};
+
+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

+ 194 - 0
3rdparty/soci/include/soci/empty/soci-empty.h

@@ -0,0 +1,194 @@
+//
+// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_EMPTY_H_INCLUDED
+#define SOCI_EMPTY_H_INCLUDED
+
+#include <soci/soci-platform.h>
+
+#ifdef SOCI_EMPTY_SOURCE
+# define SOCI_EMPTY_DECL SOCI_DECL_EXPORT
+#else
+# define SOCI_EMPTY_DECL SOCI_DECL_IMPORT
+#endif
+
+#include <soci/soci-backend.h>
+
+#include <cstddef>
+#include <string>
+
+namespace soci
+{
+
+struct empty_statement_backend;
+
+struct SOCI_EMPTY_DECL empty_standard_into_type_backend : details::standard_into_type_backend
+{
+    empty_standard_into_type_backend(empty_statement_backend &st)
+        : statement_(st)
+    {}
+
+    void define_by_pos(int& position, void* data, details::exchange_type type) override;
+
+    void pre_fetch() override;
+    void post_fetch(bool gotData, bool calledFromFetch, indicator* ind) override;
+
+    void clean_up() override;
+
+    empty_statement_backend& statement_;
+};
+
+struct SOCI_EMPTY_DECL empty_vector_into_type_backend : details::vector_into_type_backend
+{
+    empty_vector_into_type_backend(empty_statement_backend &st)
+        : statement_(st)
+    {}
+
+    void define_by_pos(int& position, void* data, details::exchange_type type) override;
+
+    void pre_fetch() override;
+    void post_fetch(bool gotData, indicator* ind) override;
+
+    void resize(std::size_t sz) override;
+    std::size_t size() override;
+
+    void clean_up() override;
+
+    empty_statement_backend& statement_;
+};
+
+struct SOCI_EMPTY_DECL empty_standard_use_type_backend : details::standard_use_type_backend
+{
+    empty_standard_use_type_backend(empty_statement_backend &st)
+        : statement_(st)
+    {}
+
+    void bind_by_pos(int& position, void* data, details::exchange_type type, bool readOnly) override;
+    void bind_by_name(std::string const& name, void* data, details::exchange_type type, bool readOnly) override;
+
+    void pre_use(indicator const* ind) override;
+    void post_use(bool gotData, indicator* ind) override;
+
+    void clean_up() override;
+
+    empty_statement_backend& statement_;
+};
+
+struct SOCI_EMPTY_DECL empty_vector_use_type_backend : details::vector_use_type_backend
+{
+    empty_vector_use_type_backend(empty_statement_backend &st)
+        : statement_(st) {}
+
+    void bind_by_pos(int& position, void* data, details::exchange_type type) override;
+    void bind_by_name(std::string const& name, void* data, details::exchange_type type) override;
+
+    void pre_use(indicator const* ind) override;
+
+    std::size_t size() override;
+
+    void clean_up() override;
+
+    empty_statement_backend& statement_;
+};
+
+struct empty_session_backend;
+struct SOCI_EMPTY_DECL empty_statement_backend : details::statement_backend
+{
+    empty_statement_backend(empty_session_backend &session);
+
+    void alloc() override;
+    void clean_up() override;
+    void prepare(std::string const& query, details::statement_type eType) override;
+
+    exec_fetch_result execute(int number) override;
+    exec_fetch_result fetch(int number) override;
+
+    long long get_affected_rows() override;
+    int get_number_of_rows() override;
+    std::string get_parameter_name(int index) const override;
+
+    std::string rewrite_for_procedure_call(std::string const& query) override;
+
+    int prepare_for_describe() override;
+    void describe_column(int colNum, db_type& dbtype, std::string& columnName) override;
+
+    empty_standard_into_type_backend* make_into_type_backend() override;
+    empty_standard_use_type_backend* make_use_type_backend() override;
+    empty_vector_into_type_backend* make_vector_into_type_backend() override;
+    empty_vector_use_type_backend* make_vector_use_type_backend() override;
+
+    empty_session_backend& session_;
+};
+
+struct empty_rowid_backend : details::rowid_backend
+{
+    empty_rowid_backend(empty_session_backend &session);
+
+    ~empty_rowid_backend() override;
+};
+
+struct empty_blob_backend : details::blob_backend
+{
+    empty_blob_backend(empty_session_backend& session);
+
+    ~empty_blob_backend() override;
+
+    std::size_t get_len() override;
+
+    std::size_t read_from_start(void * buf, std::size_t toRead, std::size_t offset = 0) override;
+
+    std::size_t write_from_start(const void * buf, std::size_t toWrite, std::size_t offset = 0) override;
+
+    std::size_t append(const void* buf, std::size_t toWrite) override;
+    void trim(std::size_t newLen) override;
+
+    empty_session_backend& session_;
+};
+
+struct empty_session_backend : details::session_backend
+{
+    empty_session_backend(connection_parameters const& parameters);
+
+    ~empty_session_backend() override;
+
+    bool is_connected() override { return true; }
+
+    void begin() override;
+    void commit() override;
+    void rollback() override;
+
+    std::string get_dummy_from_table() const override { return std::string(); }
+
+    std::string get_backend_name() const override { return "empty"; }
+
+    void clean_up();
+
+    empty_statement_backend* make_statement_backend() override;
+    empty_rowid_backend* make_rowid_backend() override;
+    empty_blob_backend* make_blob_backend() override;
+};
+
+struct SOCI_EMPTY_DECL empty_backend_factory : backend_factory
+{
+    empty_backend_factory() {}
+    empty_session_backend* make_session(connection_parameters const& parameters) const override;
+};
+
+extern SOCI_EMPTY_DECL empty_backend_factory const empty;
+
+extern "C"
+{
+
+// for dynamic backend loading
+SOCI_EMPTY_DECL backend_factory const* factory_empty();
+SOCI_EMPTY_DECL void register_factory_empty();
+
+} // extern "C"
+
+} // namespace soci
+
+#endif // SOCI_EMPTY_H_INCLUDED

+ 66 - 0
3rdparty/soci/include/soci/error.h

@@ -0,0 +1,66 @@
+//
+// Copyright (C) 2004-2008 Maciej Sobczak
+// Copyright (C) 2015 Vadim Zeitlin
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_ERROR_H_INCLUDED
+#define SOCI_ERROR_H_INCLUDED
+
+#include "soci/soci-platform.h"
+// std
+#include <stdexcept>
+#include <string>
+
+namespace soci
+{
+
+class SOCI_DECL soci_error : public std::runtime_error
+{
+public:
+    explicit soci_error(std::string const & msg);
+
+    soci_error(soci_error const& e) noexcept;
+    soci_error& operator=(soci_error const& e) noexcept;
+
+    ~soci_error() noexcept override;
+
+    // Returns just the error message itself, without the context.
+    std::string get_error_message() const;
+
+    // Returns the full error message combining the message given to the ctor
+    // with all the available context records.
+    char const* what() const noexcept override;
+
+    // This is used only by SOCI itself to provide more information about the
+    // exception as it bubbles up. It can be called multiple times, with the
+    // first call adding the lowest level context and the last one -- the
+    // highest level context.
+    void add_context(std::string const& context);
+
+    // Basic error classes.
+    enum error_category
+    {
+        connection_error,
+        invalid_statement,
+        no_privilege,
+        no_data,
+        constraint_violation,
+        unknown_transaction_state,
+        system_error,
+        unknown
+    };
+
+    // Basic error classification support
+    virtual error_category get_error_category() const { return unknown; }
+
+private:
+    // Optional extra information (currently just the context data).
+    class soci_error_extra_info* info_;
+};
+
+} // namespace soci
+
+#endif // SOCI_ERROR_H_INCLUDED

+ 190 - 0
3rdparty/soci/include/soci/exchange-traits.h

@@ -0,0 +1,190 @@
+//
+// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_EXCHANGE_TRAITS_H_INCLUDED
+#define SOCI_EXCHANGE_TRAITS_H_INCLUDED
+
+#include "soci/soci-types.h"
+#include "soci/type-conversion-traits.h"
+#include "soci/soci-backend.h"
+#include "soci/type-wrappers.h"
+// std
+#include <cstdint>
+#include <ctime>
+#include <string>
+#include <vector>
+
+namespace soci
+{
+
+namespace details
+{
+
+struct basic_type_tag {};
+struct user_type_tag {};
+
+template <typename T>
+struct exchange_traits
+{
+    // this is used for tag-dispatch between implementations for basic types
+    // and user-defined types
+    typedef user_type_tag type_family;
+
+    enum // anonymous
+    {
+        x_type =
+            exchange_traits
+            <
+                typename type_conversion<T>::base_type
+            >::x_type
+    };
+};
+
+template <>
+struct exchange_traits<int8_t>
+{
+    typedef basic_type_tag type_family;
+    enum { x_type = x_int8 };
+};
+
+template <>
+struct exchange_traits<uint8_t>
+{
+    typedef basic_type_tag type_family;
+    enum { x_type = x_uint8 };
+};
+
+template <>
+struct exchange_traits<int16_t>
+{
+    typedef basic_type_tag type_family;
+    enum { x_type = x_int16 };
+};
+
+template <>
+struct exchange_traits<uint16_t>
+{
+    typedef basic_type_tag type_family;
+    enum { x_type = x_uint16 };
+};
+
+template <>
+struct exchange_traits<int32_t>
+{
+    typedef basic_type_tag type_family;
+    enum { x_type = x_int32 };
+};
+
+template <>
+struct exchange_traits<uint32_t>
+{
+    typedef basic_type_tag type_family;
+    enum { x_type = x_uint32 };
+};
+
+template <>
+struct exchange_traits<int64_t>
+{
+    typedef basic_type_tag type_family;
+    enum { x_type = x_int64 };
+};
+
+template <>
+struct exchange_traits<uint64_t>
+{
+    typedef basic_type_tag type_family;
+    enum { x_type = x_uint64 };
+};
+
+#if defined(SOCI_INT64_IS_LONG)
+template <>
+struct exchange_traits<long long> : exchange_traits<int64_t>
+{
+};
+
+template <>
+struct exchange_traits<unsigned long long> : exchange_traits<uint64_t>
+{
+};
+#elif defined(SOCI_LONG_IS_64_BIT)
+template <>
+struct exchange_traits<long> : exchange_traits<int64_t>
+{
+};
+
+template <>
+struct exchange_traits<unsigned long> : exchange_traits<uint64_t>
+{
+};
+#else
+template <>
+struct exchange_traits<long> : exchange_traits<int32_t>
+{
+};
+
+template <>
+struct exchange_traits<unsigned long> : exchange_traits<uint32_t>
+{
+};
+#endif
+
+template <>
+struct exchange_traits<double>
+{
+    typedef basic_type_tag type_family;
+    enum { x_type = x_double };
+};
+
+template <>
+struct exchange_traits<char>
+{
+    typedef basic_type_tag type_family;
+    enum { x_type = x_char };
+};
+
+template <>
+struct exchange_traits<std::string>
+{
+    typedef basic_type_tag type_family;
+    enum { x_type = x_stdstring };
+};
+
+template <>
+struct exchange_traits<std::tm>
+{
+    typedef basic_type_tag type_family;
+    enum { x_type = x_stdtm };
+};
+
+template <typename T>
+struct exchange_traits<std::vector<T> >
+{
+    typedef typename exchange_traits<T>::type_family type_family;
+    enum { x_type = exchange_traits<T>::x_type };
+};
+
+// handling of wrapper types
+
+template <>
+struct exchange_traits<xml_type>
+{
+    typedef basic_type_tag type_family;
+    enum { x_type = x_xmltype };
+};
+
+template <>
+struct exchange_traits<long_string>
+{
+    typedef basic_type_tag type_family;
+    enum { x_type = x_longstring };
+};
+
+} // namespace details
+
+} // namespace soci
+
+#endif // SOCI_EXCHANGE_TRAITS_H_INCLUDED

+ 356 - 0
3rdparty/soci/include/soci/firebird/soci-firebird.h

@@ -0,0 +1,356 @@
+//
+// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, Rafal Bobrowski
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+//
+
+#ifndef SOCI_FIREBIRD_H_INCLUDED
+#define SOCI_FIREBIRD_H_INCLUDED
+
+#include <soci/soci-platform.h>
+
+#ifdef SOCI_FIREBIRD_SOURCE
+# define SOCI_FIREBIRD_DECL SOCI_DECL_EXPORT
+#else
+# define SOCI_FIREBIRD_DECL SOCI_DECL_IMPORT
+#endif
+
+#ifdef _WIN32
+#include <ciso646> // To understand and/or/not on MSVC9
+#endif
+#include <soci/soci-backend.h>
+#include <ibase.h> // FireBird
+#include <cstdlib>
+#include <vector>
+#include <string>
+#include <cstdint>
+
+namespace soci
+{
+
+std::size_t const stat_size = 20;
+
+// size of buffer for error messages. All examples use this value.
+// Anyone knows, where it is stated that 512 bytes is enough ?
+std::size_t const SOCI_FIREBIRD_ERRMSG = 512;
+
+class SOCI_FIREBIRD_DECL firebird_soci_error : public soci_error
+{
+public:
+    firebird_soci_error(std::string const & msg,
+        ISC_STATUS const * status = 0);
+
+    ~firebird_soci_error() noexcept override {};
+
+    std::vector<ISC_STATUS> status_;
+};
+
+enum BuffersType
+{
+    eStandard, eVector
+};
+
+struct firebird_blob_backend;
+struct firebird_statement_backend;
+struct firebird_standard_into_type_backend : details::standard_into_type_backend
+{
+    firebird_standard_into_type_backend(firebird_statement_backend &st)
+        : statement_(st), data_(NULL), type_(), position_(0), buf_(NULL), indISCHolder_(0)
+    {}
+
+    void define_by_pos(int &position,
+        void *data, details::exchange_type type) override;
+
+    void pre_fetch() override;
+    void post_fetch(bool gotData, bool calledFromFetch,
+        indicator *ind) override;
+
+    void clean_up() override;
+
+    firebird_statement_backend &statement_;
+    virtual void exchangeData();
+
+    void *data_;
+    details::exchange_type type_;
+    int position_;
+
+    char *buf_;
+    short indISCHolder_;
+};
+
+struct firebird_vector_into_type_backend : details::vector_into_type_backend
+{
+    firebird_vector_into_type_backend(firebird_statement_backend &st)
+        : statement_(st), data_(NULL), type_(), position_(0), buf_(NULL), indISCHolder_(0)
+    {}
+
+    void define_by_pos(int &position,
+        void *data, details::exchange_type type) override;
+
+    void pre_fetch() override;
+    void post_fetch(bool gotData, indicator *ind) override;
+
+    void resize(std::size_t sz) override;
+    std::size_t size() override;
+
+    void clean_up() override;
+
+    firebird_statement_backend &statement_;
+    virtual void exchangeData(std::size_t row);
+
+    void *data_;
+    details::exchange_type type_;
+    int position_;
+
+    char *buf_;
+    short indISCHolder_;
+};
+
+struct firebird_standard_use_type_backend : details::standard_use_type_backend
+{
+    firebird_standard_use_type_backend(firebird_statement_backend &st)
+        : statement_(st), data_(NULL), type_(), position_(0), buf_(NULL), indISCHolder_(0),
+          blob_(NULL)
+    {}
+
+    void bind_by_pos(int &position,
+        void *data, details::exchange_type type, bool readOnly) override;
+    void bind_by_name(std::string const &name,
+        void *data, details::exchange_type type, bool readOnly) override;
+
+    void pre_use(indicator const *ind) override;
+    void post_use(bool gotData, indicator *ind) override;
+
+    void clean_up() override;
+
+    firebird_statement_backend &statement_;
+    virtual void exchangeData();
+
+    void *data_;
+    details::exchange_type type_;
+    int position_;
+
+    char *buf_;
+    short indISCHolder_;
+
+private:
+    // Allocate a temporary blob, fill it with the data from the provided
+    // string and copy its ID into buf_.
+    void copy_to_blob(const std::string& in);
+
+    // This is used for types mapping to CLOB.
+    firebird_blob_backend* blob_;
+};
+
+struct firebird_vector_use_type_backend : details::vector_use_type_backend
+{
+    firebird_vector_use_type_backend(firebird_statement_backend &st)
+        : statement_(st), data_(NULL), type_(), position_(0), buf_(NULL), indISCHolder_(0),
+          blob_(NULL)
+    {}
+
+    void bind_by_pos(int &position,
+        void *data, details::exchange_type type) override;
+    void bind_by_name(std::string const &name,
+        void *data, details::exchange_type type) override;
+
+    void pre_use(indicator const *ind) override;
+
+    std::size_t size() override;
+
+    void clean_up() override;
+
+    firebird_statement_backend &statement_;
+    virtual void exchangeData(std::size_t row);
+
+    void *data_;
+    details::exchange_type type_;
+    int position_;
+    indicator const *inds_;
+
+    char *buf_;
+    short indISCHolder_;
+
+private:
+    // Allocate a temporary blob, fill it with the data from the provided
+    // string and copy its ID into buf_.
+    void copy_to_blob(const std::string &in);
+
+    // This is used for types mapping to CLOB.
+    firebird_blob_backend *blob_;
+};
+
+struct firebird_session_backend;
+struct firebird_statement_backend : details::statement_backend
+{
+    firebird_statement_backend(firebird_session_backend &session);
+
+    void alloc() override;
+    void clean_up() override;
+    void prepare(std::string const &query,
+        details::statement_type eType) override;
+
+    exec_fetch_result execute(int number) override;
+    exec_fetch_result fetch(int number) override;
+
+    long long get_affected_rows() override;
+    int get_number_of_rows() override;
+    std::string get_parameter_name(int index) const override;
+
+    std::string rewrite_for_procedure_call(std::string const &query) override;
+
+    int prepare_for_describe() override;
+    void describe_column(int colNum,
+        db_type &dbtype,
+        std::string &columnName) override;
+
+    firebird_standard_into_type_backend * make_into_type_backend() override;
+    firebird_standard_use_type_backend * make_use_type_backend() override;
+    firebird_vector_into_type_backend * make_vector_into_type_backend() override;
+    firebird_vector_use_type_backend * make_vector_use_type_backend() override;
+
+    firebird_session_backend &session_;
+
+    isc_stmt_handle stmtp_;
+    XSQLDA * sqldap_;
+    XSQLDA * sqlda2p_;
+
+    bool boundByName_;
+    bool boundByPos_;
+
+    friend struct firebird_vector_into_type_backend;
+    friend struct firebird_standard_into_type_backend;
+    friend struct firebird_vector_use_type_backend;
+    friend struct firebird_standard_use_type_backend;
+
+protected:
+    int rowsFetched_;
+    bool endOfRowSet_;
+
+    long long rowsAffectedBulk_; // number of rows affected by the last bulk operation
+
+    virtual void exchangeData(bool gotData, int row);
+    virtual void prepareSQLDA(XSQLDA ** sqldap, short size = 10);
+    virtual void rewriteQuery(std::string const & query,
+        std::vector<char> & buffer);
+    virtual void rewriteParameters(std::string const & src,
+        std::vector<char> & dst);
+
+    BuffersType intoType_;
+    BuffersType useType_;
+
+    std::vector<std::vector<indicator> > inds_;
+    std::vector<void*> intos_;
+    std::vector<void*> uses_;
+
+    // named parameters
+    std::map <std::string, int> names_;
+
+    bool procedure_;
+};
+
+struct firebird_blob_backend : details::blob_backend
+{
+    firebird_blob_backend(firebird_session_backend &session);
+
+    ~firebird_blob_backend() override;
+
+    std::size_t get_len() override;
+
+    std::size_t read_from_start(void * buf, std::size_t toRead, std::size_t offset = 0) override;
+
+    std::size_t write_from_start(const void * buf, std::size_t toWrite, std::size_t offset = 0) override;
+
+    std::size_t append(const void *buf, std::size_t toWrite) override;
+    void trim(std::size_t newLen) override;
+
+    // Writes the current data into the database by allocating a new BLOB
+    // object for it.
+    //
+    // Returns The ID of the newly created BLOB object
+    ISC_QUAD save_to_db();
+    void assign(ISC_QUAD const & bid);
+
+private:
+    void open();
+    long getBLOBInfo();
+    void load();
+    void writeBuffer(std::size_t offset, void const * buf,
+        std::size_t toWrite);
+    void closeBlob();
+
+    firebird_session_backend &session_;
+    ISC_QUAD blob_id_;
+    // BLOB id was fetched from database (true)
+    // or this is new BLOB
+    bool from_db_;
+    isc_blob_handle blob_handle_;
+    // buffer for BLOB data
+    std::vector<std::uint8_t> data_;
+    bool loaded_;
+    long max_seg_size_;
+};
+
+struct firebird_session_backend : details::session_backend
+{
+    firebird_session_backend(connection_parameters const & parameters);
+
+    ~firebird_session_backend() override;
+
+    bool is_connected() override;
+
+    void begin() override;
+    void commit() override;
+    void rollback() override;
+
+    bool get_next_sequence_value(session & s,
+        std::string const & sequence, long long & value) override;
+
+    std::string get_dummy_from_table() const override { return "rdb$database"; }
+
+    std::string get_backend_name() const override { return "firebird"; }
+
+    void cleanUp();
+
+    firebird_statement_backend * make_statement_backend() override;
+    details::rowid_backend* make_rowid_backend() override;
+    firebird_blob_backend * make_blob_backend() override;
+
+    bool get_option_decimals_as_strings() { return decimals_as_strings_; }
+
+    // Returns the pointer to the current transaction handle, starting a new
+    // transaction if necessary.
+    //
+    // The returned pointer should
+    isc_tr_handle* current_transaction();
+
+    isc_db_handle dbhp_;
+
+private:
+    isc_tr_handle trhp_;
+    bool decimals_as_strings_;
+};
+
+struct firebird_backend_factory : backend_factory
+{
+    firebird_backend_factory() {}
+    firebird_session_backend * make_session(
+        connection_parameters const & parameters) const override;
+};
+
+extern SOCI_FIREBIRD_DECL firebird_backend_factory const firebird;
+
+extern "C"
+{
+
+// for dynamic backend loading
+SOCI_FIREBIRD_DECL backend_factory const * factory_firebird();
+SOCI_FIREBIRD_DECL void register_factory_firebird();
+
+} // extern "C"
+
+} // namespace soci
+
+#endif // SOCI_FIREBIRD_H_INCLUDED

+ 155 - 0
3rdparty/soci/include/soci/fixed-size-ints.h

@@ -0,0 +1,155 @@
+#ifndef SOCI_FIXED_SIZE_INTS_H_INCLUDED
+#define SOCI_FIXED_SIZE_INTS_H_INCLUDED
+
+#include "soci/soci-types.h"
+#include "soci/type-conversion-traits.h"
+
+#include <cstdint>
+
+namespace soci
+{
+
+// Completion of dt_[u]int* bindings for all architectures.
+// This allows us to extract values on types where the type definition is
+// specific to the underlying architecture. E.g. Unix defines a int64_t as
+// long. This would make it impossible to extract a dt_int64 value as both
+// long and long long. With the following type_conversion specializations,
+// this becomes possible.
+
+#if defined(SOCI_INT64_IS_LONG)
+template <>
+struct type_conversion<long long>
+{
+    typedef int64_t base_type;
+
+    static void from_base(base_type const & in, indicator ind, long long & out)
+    {
+        if (ind == i_null)
+        {
+            throw soci_error("Null value not allowed for this type.");
+        }
+
+        out = static_cast<long long>(in);
+    }
+
+    static void to_base(long long const & in, base_type & out, indicator & ind)
+    {
+        out = static_cast<base_type>(in);
+        ind = i_ok;
+    }
+};
+
+template <>
+struct type_conversion<unsigned long long>
+{
+    typedef uint64_t base_type;
+
+    static void from_base(base_type const & in, indicator ind, unsigned long long & out)
+    {
+        if (ind == i_null)
+        {
+            throw soci_error("Null value not allowed for this type.");
+        }
+
+        out = static_cast<unsigned long long>(in);
+    }
+
+    static void to_base(unsigned long long const & in, base_type & out, indicator & ind)
+    {
+        out = static_cast<base_type>(in);
+        ind = i_ok;
+    }
+};
+#elif defined(SOCI_LONG_IS_64_BIT)
+template <>
+struct type_conversion<long>
+{
+    typedef int64_t base_type;
+
+    static void from_base(base_type const & in, indicator ind, long & out)
+    {
+        if (ind == i_null)
+        {
+            throw soci_error("Null value not allowed for this type.");
+        }
+
+        out = static_cast<long>(in);
+    }
+
+    static void to_base(long const & in, base_type & out, indicator & ind)
+    {
+        out = static_cast<base_type>(in);
+        ind = i_ok;
+    }
+};
+
+template <>
+struct type_conversion<unsigned long>
+{
+    typedef uint64_t base_type;
+
+    static void from_base(base_type const & in, indicator ind, unsigned long & out)
+    {
+        if (ind == i_null)
+        {
+            throw soci_error("Null value not allowed for this type.");
+        }
+
+        out = static_cast<unsigned long>(in);
+    }
+
+    static void to_base(unsigned long const & in, base_type & out, indicator & ind)
+    {
+        out = static_cast<base_type>(in);
+        ind = i_ok;
+    }
+};
+#else
+template <>
+struct type_conversion<long>
+{
+    typedef int32_t base_type;
+
+    static void from_base(base_type const & in, indicator ind, long & out)
+    {
+        if (ind == i_null)
+        {
+            throw soci_error("Null value not allowed for this type.");
+        }
+
+        out = static_cast<long>(in);
+    }
+
+    static void to_base(long const & in, base_type & out, indicator & ind)
+    {
+        out = static_cast<base_type>(in);
+        ind = i_ok;
+    }
+};
+
+template <>
+struct type_conversion<unsigned long>
+{
+    typedef uint32_t base_type;
+
+    static void from_base(base_type const & in, indicator ind, unsigned long & out)
+    {
+        if (ind == i_null)
+        {
+            throw soci_error("Null value not allowed for this type.");
+        }
+
+        out = static_cast<unsigned long>(in);
+    }
+
+    static void to_base(unsigned long const & in, base_type & out, indicator & ind)
+    {
+        out = static_cast<base_type>(in);
+        ind = i_ok;
+    }
+};
+#endif
+
+} // namespace soci
+
+#endif // SOCI_FIXED_SIZE_INTS_H_INCLUDED

+ 213 - 0
3rdparty/soci/include/soci/into-type.h

@@ -0,0 +1,213 @@
+//
+// Copyright (C) 2004-2016 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_INTO_TYPE_H_INCLUDED
+#define SOCI_INTO_TYPE_H_INCLUDED
+
+#include "soci/soci-backend.h"
+#include "soci/type-ptr.h"
+#include "soci/exchange-traits.h"
+// std
+#include <cstddef>
+#include <vector>
+
+namespace soci
+{
+
+class session;
+
+namespace details
+{
+
+class prepare_temp_type;
+class standard_into_type_backend;
+class vector_into_type_backend;
+class statement_impl;
+
+// this is intended to be a base class for all classes that deal with
+// defining output data
+class into_type_base
+{
+public:
+    virtual ~into_type_base() {}
+
+    virtual void define(statement_impl & st, int & position) = 0;
+    virtual void pre_exec(int num) = 0;
+    virtual void pre_fetch() = 0;
+    virtual void post_fetch(bool gotData, bool calledFromFetch) = 0;
+    virtual void clean_up() = 0;
+
+    virtual std::size_t size() const = 0;  // returns the number of elements
+    virtual void resize(std::size_t /* sz */) {} // used for vectors only
+};
+
+typedef type_ptr<into_type_base> into_type_ptr;
+
+// standard types
+
+class SOCI_DECL standard_into_type : public into_type_base
+{
+public:
+    standard_into_type(void * data, exchange_type type)
+        : data_(data), type_(type), ind_(NULL), backEnd_(NULL) {}
+    standard_into_type(void * data, exchange_type type, indicator & ind)
+        : data_(data), type_(type), ind_(&ind), backEnd_(NULL)
+    {
+        // Backends won't initialize the indicator if no data is retrieved, so
+        // do it here, like this we can be sure it has a defined value even if
+        // an exception is thrown before anything else happens.
+        *ind_ = i_null;
+    }
+
+    ~standard_into_type() override;
+
+protected:
+    void post_fetch(bool gotData, bool calledFromFetch) override;
+
+private:
+    void define(statement_impl & st, int & position) override;
+    void pre_exec(int num) override;
+    void pre_fetch() override;
+    void clean_up() override;
+
+    std::size_t size() const override { return 1; }
+
+    // conversion hook (from base type to arbitrary user type)
+    virtual void convert_from_base() {}
+
+    void * data_;
+    exchange_type type_;
+    indicator * ind_;
+
+    standard_into_type_backend * backEnd_;
+};
+
+// into type base class for vectors
+class SOCI_DECL vector_into_type : public into_type_base
+{
+public:
+    vector_into_type(void * data, exchange_type type)
+        : data_(data), type_(type), indVec_(NULL),
+        begin_(0), end_(NULL), backEnd_(NULL) {}
+
+    vector_into_type(void * data, exchange_type type,
+        std::size_t begin, std::size_t * end)
+        : data_(data), type_(type), indVec_(NULL),
+        begin_(begin), end_(end), backEnd_(NULL) {}
+
+    vector_into_type(void * data, exchange_type type,
+        std::vector<indicator> & ind)
+        : data_(data), type_(type), indVec_(&ind),
+        begin_(0), end_(NULL), backEnd_(NULL) {}
+
+    vector_into_type(void * data, exchange_type type,
+        std::vector<indicator> & ind,
+        std::size_t begin, std::size_t * end)
+        : data_(data), type_(type), indVec_(&ind),
+        begin_(begin), end_(end), backEnd_(NULL) {}
+
+    ~vector_into_type() override;
+
+protected:
+    void post_fetch(bool gotData, bool calledFromFetch) override;
+
+    void define(statement_impl & st, int & position) override;
+    void pre_exec(int num) override;
+    void pre_fetch() override;
+    void clean_up() override;
+    void resize(std::size_t sz) override;
+    std::size_t size() const override;
+
+    void * data_;
+    exchange_type type_;
+    std::vector<indicator> * indVec_;
+    std::size_t begin_;
+    std::size_t * end_;
+
+    vector_into_type_backend * backEnd_;
+
+    virtual void convert_from_base() {}
+};
+
+// implementation for the basic types (those which are supported by the library
+// out of the box without user-provided conversions)
+
+template <typename T>
+class into_type : public standard_into_type
+{
+public:
+    into_type(T & t)
+        : standard_into_type(&t,
+            static_cast<exchange_type>(exchange_traits<T>::x_type)) {}
+    into_type(T & t, indicator & ind)
+        : standard_into_type(&t,
+            static_cast<exchange_type>(exchange_traits<T>::x_type), ind) {}
+};
+
+template <typename T>
+class into_type<std::vector<T> > : public vector_into_type
+{
+public:
+    into_type(std::vector<T> & v)
+        : vector_into_type(&v,
+            static_cast<exchange_type>(exchange_traits<T>::x_type)) {}
+
+    into_type(std::vector<T> & v, std::size_t begin, std::size_t * end)
+        : vector_into_type(&v,
+            static_cast<exchange_type>(exchange_traits<T>::x_type),
+            begin, end) {}
+
+    into_type(std::vector<T> & v, std::vector<indicator> & ind)
+        : vector_into_type(&v,
+            static_cast<exchange_type>(exchange_traits<T>::x_type), ind) {}
+
+    into_type(std::vector<T> & v, std::vector<indicator> & ind,
+        std::size_t begin, std::size_t * end)
+        : vector_into_type(&v,
+            static_cast<exchange_type>(exchange_traits<T>::x_type), ind,
+            begin, end) {}
+};
+
+// helper dispatchers for basic types
+
+template <typename T>
+into_type_ptr do_into(T & t, basic_type_tag)
+{
+    return into_type_ptr(new into_type<T>(t));
+}
+
+template <typename T>
+into_type_ptr do_into(T & t, indicator & ind, basic_type_tag)
+{
+    return into_type_ptr(new into_type<T>(t, ind));
+}
+
+template <typename T>
+into_type_ptr do_into(T & t, std::vector<indicator> & ind, basic_type_tag)
+{
+    return into_type_ptr(new into_type<T>(t, ind));
+}
+
+template <typename T>
+into_type_ptr do_into(std::vector<T> & t,
+    std::size_t begin, std::size_t * end, basic_type_tag)
+{
+    return into_type_ptr(new into_type<std::vector<T> >(t, begin, end));
+}
+
+template <typename T>
+into_type_ptr do_into(std::vector<T> & t, std::vector<indicator> & ind,
+    std::size_t begin, std::size_t * end, basic_type_tag)
+{
+    return into_type_ptr(new into_type<std::vector<T> >(t, ind, begin, end));
+}
+
+} // namespace details
+
+} // namespace soci
+
+#endif // SOCI_INTO_TYPE_H_INCLUDED

+ 97 - 0
3rdparty/soci/include/soci/into.h

@@ -0,0 +1,97 @@
+//
+// Copyright (C) 2004-2016 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_INTO_H_INCLUDED
+#define SOCI_INTO_H_INCLUDED
+
+#include "soci/into-type.h"
+#include "soci/exchange-traits.h"
+#include "soci/type-conversion.h"
+// std
+#include <cstddef>
+#include <vector>
+
+namespace soci
+{
+
+// the into function is a helper for defining output variables
+// these helpers work with both basic and user-defined types thanks to
+// the tag-dispatching, as defined in exchange_traits template
+
+namespace details
+{
+template <typename T, typename Indicator>
+struct into_container
+{
+    into_container(T &_t, Indicator &_ind)
+        : t(_t), ind(_ind) {}
+
+    T &t;
+    Indicator &ind;
+private:
+    SOCI_NOT_ASSIGNABLE(into_container)
+};
+
+typedef void no_indicator;
+template <typename T>
+struct into_container<T, no_indicator>
+{
+    into_container(T &_t)
+        : t(_t) {}
+
+    T &t;
+private:
+    SOCI_NOT_ASSIGNABLE(into_container)
+};
+
+} // namespace details
+
+template <typename T>
+details::into_container<T, details::no_indicator>
+    into(T &t)
+{ return details::into_container<T, details::no_indicator>(t); }
+
+template <typename T, typename Indicator>
+details::into_container<T, Indicator>
+    into(T &t, Indicator &ind)
+{ return details::into_container<T, Indicator>(t, ind); }
+
+// for char buffer with run-time size information
+template <typename T>
+details::into_type_ptr into(T & t, std::size_t bufSize)
+{
+    return details::into_type_ptr(new details::into_type<T>(t, bufSize));
+}
+
+// vectors with index ranges
+
+template <typename T>
+details::into_type_ptr into(std::vector<T> & t,
+    std::size_t begin, std::size_t & end)
+{
+    return details::do_into(t, begin, &end,
+        typename details::exchange_traits<std::vector<T> >::type_family());
+}
+
+template <typename T>
+details::into_type_ptr into(std::vector<T> & t, std::vector<indicator> & ind)
+{
+    return details::do_into(t, ind,
+        typename details::exchange_traits<std::vector<T> >::type_family());
+}
+
+template <typename T>
+details::into_type_ptr into(std::vector<T> & t, std::vector<indicator> & ind,
+    std::size_t begin, std::size_t & end)
+{
+    return details::do_into(t, ind, begin, &end,
+        typename details::exchange_traits<std::vector<T> >::type_family());
+}
+
+} // namespace soci
+
+#endif // SOCI_INTO_H_INCLUDED

+ 49 - 0
3rdparty/soci/include/soci/is-detected.h

@@ -0,0 +1,49 @@
+//
+// Copyright (C) 2023 Robert Adam
+// 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_IS_DETECTED_H_INCLUDED
+#define SOCI_IS_DETECTED_H_INCLUDED
+
+#include <type_traits>
+
+namespace soci
+{
+
+namespace details
+{
+
+template<typename...>
+using void_t = void;
+
+using false_type = std::integral_constant<bool, false>;
+using true_type = std::integral_constant<bool, true>;
+
+// Implementation from https://blog.tartanllama.xyz/detection-idiom/
+// Note, this is a stub that we require until standard C++ gets support
+// for the detection idiom that is not experimental (and thus can be
+// assumed to be present).
+
+namespace detector_detail
+{
+
+    template <template <class...> class Trait, class Enabler, class... Args>
+    struct is_detected : false_type {};
+
+    template <template <class...> class Trait, class... Args>
+    struct is_detected<Trait, void_t<Trait<Args...>>, Args...> : true_type {};
+
+}
+
+
+template <template <class...> class Trait, class... Args>
+using is_detected = typename detector_detail::is_detected<Trait, void, Args...>::type;
+
+}
+
+}
+
+#endif // SOCI_IS_DETECTED_H_INCLUDED

+ 82 - 0
3rdparty/soci/include/soci/logger.h

@@ -0,0 +1,82 @@
+//
+// Copyright (C) 2014 Vadim Zeitlin
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_LOGGER_H_INCLUDED
+#define SOCI_LOGGER_H_INCLUDED
+
+#include "soci/soci-platform.h"
+
+#include <ostream>
+
+namespace soci
+{
+
+// Allows to customize the logging of database operations performed by SOCI.
+//
+// To do it, derive your own class from logger_impl and override its pure
+// virtual start_query() and do_clone() methods (overriding the other methods
+// is optional), then call session::set_logger() with a logger object using
+// your implementation.
+class SOCI_DECL logger_impl
+{
+public:
+    logger_impl() {}
+    virtual ~logger_impl();
+
+    // Called to indicate that a new query is about to be executed.
+    virtual void start_query(std::string const & query) = 0;
+
+    logger_impl * clone() const;
+
+    // These methods are for compatibility only as they're used to implement
+    // session basic logging support, you should only override them if you want
+    // to use session::set_stream() and similar methods with your custom logger.
+    virtual void set_stream(std::ostream * s);
+    virtual std::ostream * get_stream() const;
+    virtual std::string get_last_query() const;
+
+private:
+    // Override to return a new heap-allocated copy of this object.
+    virtual logger_impl * do_clone() const = 0;
+
+    // Non-copyable
+    logger_impl(logger_impl const &);
+    logger_impl & operator=(logger_impl const &);
+};
+
+
+// A wrapper class representing a logger.
+//
+// Unlike logger_impl, this class has value semantics and can be manipulated
+// easily without any danger of memory leaks or dereferencing a NULL pointer.
+class SOCI_DECL logger
+{
+public:
+    // No default constructor, must always have an associated logger_impl.
+
+    // Create a logger using the provided non-NULL implementation (an exception
+    // is thrown if the pointer is NULL). The logger object takes ownership of
+    // the pointer and will delete it.
+    logger(logger_impl * impl);
+    logger(logger const & other);
+    logger& operator=(logger const & other);
+    ~logger();
+
+    void start_query(std::string const & query) { m_impl->start_query(query); }
+
+    // Methods used for the implementation of session basic logging support.
+    void set_stream(std::ostream * s) { m_impl->set_stream(s); }
+    std::ostream * get_stream() const { return m_impl->get_stream(); }
+    std::string get_last_query() const { return m_impl->get_last_query(); }
+
+private:
+    logger_impl * m_impl;
+};
+
+} // namespace soci
+
+#endif // SOCI_LOGGER_H_INCLUDED

+ 314 - 0
3rdparty/soci/include/soci/mysql/soci-mysql.h

@@ -0,0 +1,314 @@
+//
+// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton
+// MySQL backend copyright (C) 2006 Pawel Aleksander Fedorynski
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_MYSQL_H_INCLUDED
+#define SOCI_MYSQL_H_INCLUDED
+
+#include <soci/soci-platform.h>
+
+#ifdef SOCI_MYSQL_SOURCE
+# define SOCI_MYSQL_DECL SOCI_DECL_EXPORT
+#else
+# define SOCI_MYSQL_DECL SOCI_DECL_IMPORT
+#endif
+
+#include <soci/soci-backend.h>
+#include <private/soci-trivial-blob-backend.h>
+#ifdef _WIN32
+#include <winsock.h> // SOCKET
+#endif // _WIN32
+
+// Some version of mysql.h contain trailing comma in an enum declaration that
+// trigger -Wpedantic, so suppress it as there is nothing to be done about it
+// using the macros defined in our private soci-compiler.h header, that we can
+// only include when building SOCI itself.
+#ifdef SOCI_MYSQL_SOURCE
+    #include "soci-compiler.h"
+#endif
+
+#ifdef SOCI_GCC_WARNING_SUPPRESS
+    SOCI_GCC_WARNING_SUPPRESS(pedantic)
+#endif
+
+#include <mysql.h> // MySQL Client
+#include <errmsg.h> // MySQL Error codes
+
+#ifdef SOCI_GCC_WARNING_RESTORE
+    SOCI_GCC_WARNING_RESTORE(pedantic)
+#endif
+
+#include <vector>
+
+
+namespace soci
+{
+
+class SOCI_MYSQL_DECL mysql_soci_error : public soci_error
+{
+public:
+    mysql_soci_error(std::string const & msg, int errNum)
+        : soci_error(msg), err_num_(errNum), cat_(unknown) {
+            if(errNum == CR_CONNECTION_ERROR ||
+               errNum == CR_CONN_HOST_ERROR ||
+               errNum == CR_SERVER_GONE_ERROR ||
+               errNum == CR_SERVER_LOST ||
+               errNum == 1927) { // Lost connection to backend server
+                cat_ = connection_error;
+            }
+        }
+
+    error_category get_error_category() const override { return cat_; }
+
+    unsigned int err_num_;
+    error_category cat_;
+};
+
+struct mysql_statement_backend;
+struct mysql_standard_into_type_backend : details::standard_into_type_backend
+{
+    mysql_standard_into_type_backend(mysql_statement_backend &st)
+        : statement_(st) {}
+
+    void define_by_pos(int &position,
+        void *data, details::exchange_type type) override;
+
+    void pre_fetch() override;
+    void post_fetch(bool gotData, bool calledFromFetch,
+        indicator *ind) override;
+
+    void clean_up() override;
+
+    mysql_statement_backend &statement_;
+
+    void *data_;
+    details::exchange_type type_;
+    int position_;
+};
+
+struct mysql_vector_into_type_backend : details::vector_into_type_backend
+{
+    mysql_vector_into_type_backend(mysql_statement_backend &st)
+        : statement_(st) {}
+
+    void define_by_pos(int &position,
+        void *data, details::exchange_type type) override;
+
+    void pre_fetch() override;
+    void post_fetch(bool gotData, indicator *ind) override;
+
+    void resize(std::size_t sz) override;
+    std::size_t size() override;
+
+    void clean_up() override;
+
+    mysql_statement_backend &statement_;
+
+    void *data_;
+    details::exchange_type type_;
+    int position_;
+};
+
+struct mysql_standard_use_type_backend : details::standard_use_type_backend
+{
+    mysql_standard_use_type_backend(mysql_statement_backend &st)
+        : statement_(st), position_(0), buf_(NULL) {}
+
+    void bind_by_pos(int &position,
+        void *data, details::exchange_type type, bool readOnly) override;
+    void bind_by_name(std::string const &name,
+        void *data, details::exchange_type type, bool readOnly) override;
+
+    void pre_use(indicator const *ind) override;
+    void post_use(bool gotData, indicator *ind) override;
+
+    void clean_up() override;
+
+    mysql_statement_backend &statement_;
+
+    void *data_;
+    details::exchange_type type_;
+    int position_;
+    std::string name_;
+    char *buf_;
+};
+
+struct mysql_vector_use_type_backend : details::vector_use_type_backend
+{
+    mysql_vector_use_type_backend(mysql_statement_backend &st)
+        : statement_(st), position_(0) {}
+
+    void bind_by_pos(int &position,
+        void *data, details::exchange_type type) override;
+    void bind_by_name(std::string const &name,
+        void *data, details::exchange_type type) override;
+
+    void pre_use(indicator const *ind) override;
+
+    std::size_t size() override;
+
+    void clean_up() override;
+
+    mysql_statement_backend &statement_;
+
+    void *data_;
+    details::exchange_type type_;
+    int position_;
+    std::string name_;
+    std::vector<char *> buffers_;
+};
+
+struct mysql_session_backend;
+struct mysql_statement_backend : details::statement_backend
+{
+    mysql_statement_backend(mysql_session_backend &session);
+
+    void alloc() override;
+    void clean_up() override;
+    void prepare(std::string const &query,
+        details::statement_type eType) override;
+
+    exec_fetch_result execute(int number) override;
+    exec_fetch_result fetch(int number) override;
+
+    long long get_affected_rows() override;
+    int get_number_of_rows() override;
+    std::string get_parameter_name(int index) const override;
+
+    std::string rewrite_for_procedure_call(std::string const &query) override;
+
+    int prepare_for_describe() override;
+    void describe_column(int colNum,
+        db_type &dbtype,
+        std::string &columnName) override;
+    data_type to_data_type(db_type dbt) const override;
+
+    mysql_standard_into_type_backend * make_into_type_backend() override;
+    mysql_standard_use_type_backend * make_use_type_backend() override;
+    mysql_vector_into_type_backend * make_vector_into_type_backend() override;
+    mysql_vector_use_type_backend * make_vector_use_type_backend() override;
+
+    mysql_session_backend &session_;
+
+    MYSQL_RES *result_;
+
+    // The query is split into chunks, separated by the named parameters;
+    // e.g. for "SELECT id FROM ttt WHERE name = :foo AND gender = :bar"
+    // we will have query chunks "SELECT id FROM ttt WHERE name = ",
+    // "AND gender = " and names "foo", "bar".
+    std::vector<std::string> queryChunks_;
+    std::vector<std::string> names_; // list of names for named binds
+
+    long long rowsAffectedBulk_; // number of rows affected by the last bulk operation
+
+    int numberOfRows_;  // number of rows retrieved from the server
+    int currentRow_;    // "current" row number to consume in postFetch
+    int rowsToConsume_; // number of rows to be consumed in postFetch
+
+    bool justDescribed_; // to optimize row description with immediately
+                         // following actual statement execution
+
+    // Set to true if the last column passed to describe_column() was a
+    // MEDIUMINT UNSIGNED one, see to_data_type().
+    bool lastDescribedUnsignedMediumInt_ = false;
+
+    // Prefetch the row offsets in order to use mysql_row_seek() for
+    // random access to rows, since mysql_data_seek() is expensive.
+    std::vector<MYSQL_ROW_OFFSET> resultRowOffsets_;
+
+    bool hasIntoElements_;
+    bool hasVectorIntoElements_;
+    bool hasUseElements_;
+    bool hasVectorUseElements_;
+
+    // the following maps are used for finding data buffers according to
+    // use elements specified by the user
+
+    typedef std::map<int, char **> UseByPosBuffersMap;
+    UseByPosBuffersMap useByPosBuffers_;
+
+    typedef std::map<std::string, char **> UseByNameBuffersMap;
+    UseByNameBuffersMap useByNameBuffers_;
+};
+
+struct mysql_rowid_backend : details::rowid_backend
+{
+    mysql_rowid_backend(mysql_session_backend &session);
+
+    ~mysql_rowid_backend() override;
+};
+
+class mysql_blob_backend : public details::trivial_blob_backend
+{
+public:
+    mysql_blob_backend(mysql_session_backend &session);
+
+    ~mysql_blob_backend() override;
+
+    std::size_t hex_str_size() const;
+    void write_hex_str(char *buf, std::size_t size) const;
+    std::string as_hex_str() const;
+
+    void load_from_hex_str(const char* str, std::size_t length);
+};
+
+struct mysql_session_backend : details::session_backend
+{
+    mysql_session_backend(connection_parameters const & parameters);
+
+    ~mysql_session_backend() override;
+
+    bool is_connected() override;
+
+    void begin() override;
+    void commit() override;
+    void rollback() override;
+
+    bool get_last_insert_id(session&, std::string const&, long long&) override;
+
+    // Note that MySQL supports both "SELECT 2+2" and "SELECT 2+2 FROM DUAL"
+    // syntaxes, but there doesn't seem to be any reason to use the longer one.
+    std::string get_dummy_from_table() const override { return std::string(); }
+
+    std::string get_backend_name() const override { return "mysql"; }
+
+    void clean_up();
+
+    mysql_statement_backend * make_statement_backend() override;
+    mysql_rowid_backend * make_rowid_backend() override;
+    mysql_blob_backend * make_blob_backend() override;
+
+    std::string get_table_names_query() const override
+    {
+        return "SELECT table_name AS 'TABLE_NAME' FROM information_schema.tables WHERE table_schema = DATABASE()";
+    }
+
+    MYSQL *conn_;
+};
+
+
+struct mysql_backend_factory : backend_factory
+{
+    mysql_backend_factory() {}
+    mysql_session_backend * make_session(
+        connection_parameters const & parameters) const override;
+};
+
+extern SOCI_MYSQL_DECL mysql_backend_factory const mysql;
+
+extern "C"
+{
+
+// for dynamic backend loading
+SOCI_MYSQL_DECL backend_factory const * factory_mysql();
+SOCI_MYSQL_DECL void register_factory_mysql();
+
+} // extern "C"
+
+} // namespace soci
+
+#endif // SOCI_MYSQL_H_INCLUDED

+ 22 - 0
3rdparty/soci/include/soci/noreturn.h

@@ -0,0 +1,22 @@
+//
+// Copyright (C) 2015 Vadim Zeitlin
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_NORETURN_H_INCLUDED
+#define SOCI_NORETURN_H_INCLUDED
+
+// Define a portable SOCI_NORETURN macro.
+//
+// TODO-C++11: Use [[noreturn]] attribute.
+#if defined(__GNUC__)
+#   define SOCI_NORETURN __attribute__((noreturn)) void
+#elif defined(_MSC_VER)
+#   define SOCI_NORETURN __declspec(noreturn) void
+#else
+#   define SOCI_NORETURN void
+#endif
+
+#endif // SOCI_NORETURN_H_INCLUDED

+ 624 - 0
3rdparty/soci/include/soci/odbc/soci-odbc.h

@@ -0,0 +1,624 @@
+//
+// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_ODBC_H_INCLUDED
+#define SOCI_ODBC_H_INCLUDED
+
+#include <soci/soci-platform.h>
+
+#ifdef SOCI_ODBC_SOURCE
+# define SOCI_ODBC_DECL SOCI_DECL_EXPORT
+#else
+# define SOCI_ODBC_DECL SOCI_DECL_IMPORT
+#endif
+
+#include <vector>
+#include <soci/soci-backend.h>
+#include <sstream>
+#if defined(_MSC_VER) || defined(__MINGW32__)
+#include <windows.h>
+#endif
+#include <sqlext.h> // ODBC
+#include <string.h> // strcpy()
+
+namespace soci
+{
+
+namespace details
+{
+    // TODO: Do we want to make it a part of public interface? --mloskot
+    std::size_t const odbc_max_buffer_length = 100 * 1024 * 1024;
+
+    // select max size from following MSDN article
+    // https://msdn.microsoft.com/en-us/library/ms130896.aspx
+    SQLLEN const ODBC_MAX_COL_SIZE = 8000;
+
+    // This cast is only used to avoid compiler warnings when passing strings
+    // to ODBC functions, the returned string may *not* be really modified.
+    inline SQLCHAR* sqlchar_cast(std::string const& s)
+    {
+      return reinterpret_cast<SQLCHAR*>(const_cast<char*>(s.c_str()));
+    }
+}
+
+// Option allowing to specify the "driver completion" parameter of
+// SQLDriverConnect(). Its possible values are the same as the allowed values
+// for this parameter in the official ODBC, i.e. one of SQL_DRIVER_XXX (in
+// string form as all options are strings currently).
+extern SOCI_ODBC_DECL char const * odbc_option_driver_complete;
+
+struct odbc_statement_backend;
+
+// Helper of into and use backends.
+class odbc_standard_type_backend_base
+{
+protected:
+    odbc_standard_type_backend_base(odbc_statement_backend &st)
+        : statement_(st) {}
+
+    // Check if we need to pass 64 bit integers as strings to the database as
+    // some drivers don't support them directly.
+    inline bool use_string_for_bigint() const;
+
+    // If we do need to use strings for 64 bit integers, this constant defines
+    // the maximal string length needed.
+    enum
+    {
+        // This is the length of decimal representation of UINT64_MAX + 1.
+        max_bigint_length = 21
+    };
+
+    // IBM DB2 driver is not compliant to ODBC spec for indicators in 64bit
+    // SQLLEN is still defined 32bit (int) but spec requires 64bit (long)
+    inline bool requires_noncompliant_32bit_sqllen() const;
+    inline SQLLEN get_sqllen_from_value(const SQLLEN val) const;
+    inline void set_sqllen_from_value(SQLLEN &target, const SQLLEN val) const;
+
+    inline bool supports_negative_tinyint() const;
+    inline bool can_convert_to_unsigned_sql_type() const;
+
+    odbc_statement_backend &statement_;
+private:
+    SOCI_NOT_COPYABLE(odbc_standard_type_backend_base)
+};
+
+struct odbc_standard_into_type_backend : details::standard_into_type_backend,
+                                         private odbc_standard_type_backend_base
+{
+    odbc_standard_into_type_backend(odbc_statement_backend &st)
+        : odbc_standard_type_backend_base(st), buf_(0)
+    {}
+
+    void define_by_pos(int &position,
+        void *data, details::exchange_type type) override;
+
+    void pre_fetch() override;
+    void post_fetch(bool gotData, bool calledFromFetch,
+        indicator *ind) override;
+
+    void clean_up() override;
+
+    char *buf_;        // generic buffer
+    void *data_;
+    details::exchange_type type_;
+    int position_;
+    SQLSMALLINT odbcType_;
+    SQLLEN valueLen_;
+private:
+    SOCI_NOT_COPYABLE(odbc_standard_into_type_backend)
+};
+
+struct odbc_vector_into_type_backend : details::vector_into_type_backend,
+                                       private odbc_standard_type_backend_base
+{
+    odbc_vector_into_type_backend(odbc_statement_backend &st)
+        : odbc_standard_type_backend_base(st),
+          data_(NULL), buf_(NULL), position_(0) {}
+
+    void define_by_pos(int &position,
+        void *data, details::exchange_type type) override;
+
+    void pre_fetch() override;
+    void post_fetch(bool gotData, indicator *ind) override;
+
+    void resize(std::size_t sz) override;
+    std::size_t size() override;
+
+    void clean_up() override;
+
+    // Normally data retrieved from the database is handled in post_fetch(),
+    // however we may need to call SQLFetch() multiple times, so we call this
+    // function instead after each call to it to retrieve the given range of
+    // rows.
+    void do_post_fetch_rows(std::size_t beginRow, std::size_t endRow);
+
+    // IBM DB2 driver is not compliant to ODBC spec for indicators in 64bit
+    // SQLLEN is still defined 32bit (int) but spec requires 64bit (long)
+    inline SQLLEN get_sqllen_from_vector_at(std::size_t idx) const;
+
+    // Rebind the single vector value at the given index to the first row.
+    // Used when vector values are fetched by single row.
+    void rebind_row(std::size_t rowInd);
+
+    std::vector<SQLLEN> indHolderVec_;
+    void *data_;
+    char *buf_;              // generic buffer
+    details::exchange_type type_;
+    std::size_t colSize_;    // size of the string column (used for strings)
+    SQLSMALLINT odbcType_;
+    int position_;
+};
+
+struct odbc_standard_use_type_backend : details::standard_use_type_backend,
+                                        private odbc_standard_type_backend_base
+{
+    odbc_standard_use_type_backend(odbc_statement_backend &st)
+        : odbc_standard_type_backend_base(st),
+          position_(-1), data_(0), buf_(0), indHolder_(0) {}
+
+    void bind_by_pos(int &position,
+        void *data, details::exchange_type type, bool readOnly) override;
+    void bind_by_name(std::string const &name,
+        void *data, details::exchange_type type, bool readOnly) override;
+
+    void pre_use(indicator const *ind) override;
+    void post_use(bool gotData, indicator *ind) override;
+
+    void clean_up() override;
+
+    // Return the pointer to the buffer containing data to be used by ODBC.
+    // This can be either data_ itself or buf_, that is allocated by this
+    // function if necessary.
+    //
+    // Also fill in the size of the data and SQL and C types of it.
+    void* prepare_for_bind(SQLLEN &size,
+       SQLSMALLINT &sqlType, SQLSMALLINT &cType);
+
+    int position_;
+    void *data_;
+    details::exchange_type type_;
+    char *buf_;
+    SQLLEN indHolder_;
+
+private:
+    // Copy string data to buf_ and set size, sqlType and cType to the values
+    // appropriate for strings.
+    void copy_from_string(std::string const& s,
+                          SQLLEN& size,
+                          SQLSMALLINT& sqlType,
+                          SQLSMALLINT& cType);
+
+};
+
+struct odbc_vector_use_type_backend : details::vector_use_type_backend,
+                                      private odbc_standard_type_backend_base
+{
+    odbc_vector_use_type_backend(odbc_statement_backend &st)
+        : odbc_standard_type_backend_base(st),
+          data_(NULL), buf_(NULL) {}
+
+    // helper function for preparing indicators
+    // (as part of the define_by_pos)
+    void prepare_indicators(std::size_t size);
+
+    // helper of pre_use(), return the pointer to the data to be used by ODBC.
+    void* prepare_for_bind(SQLUINTEGER &size, SQLSMALLINT &sqlType, SQLSMALLINT &cType);
+
+    void bind_by_pos(int &position,
+        void *data, details::exchange_type type) override;
+    void bind_by_name(std::string const &name,
+        void *data, details::exchange_type type) override;
+
+    void pre_use(indicator const *ind) override;
+
+    std::size_t size() override;
+
+    void clean_up() override;
+
+    // IBM DB2 driver is not compliant to ODBC spec for indicators in 64bit
+    // SQLLEN is still defined 32bit (int) but spec requires 64bit (long)
+    inline void set_sqllen_from_vector_at(const std::size_t idx, const SQLLEN val);
+
+    std::vector<SQLLEN> indHolderVec_;
+    void *data_;
+    details::exchange_type type_;
+    int position_;
+    char *buf_;              // generic buffer
+    std::size_t colSize_;    // size of the string column (used for strings)
+    // used for strings only
+    std::size_t maxSize_;
+};
+
+struct odbc_session_backend;
+struct odbc_statement_backend : details::statement_backend
+{
+    odbc_statement_backend(odbc_session_backend &session);
+
+    void alloc() override;
+    void clean_up() override;
+    void prepare(std::string const &query,
+        details::statement_type eType) override;
+
+    exec_fetch_result execute(int number) override;
+    exec_fetch_result fetch(int number) override;
+
+    long long get_affected_rows() override;
+    int get_number_of_rows() override;
+    std::string get_parameter_name(int index) const override;
+
+    std::string rewrite_for_procedure_call(std::string const &query) override;
+
+    int prepare_for_describe() override;
+    void describe_column(int colNum,
+        db_type &dbtype,
+        std::string &columnName) override;
+    data_type to_data_type(db_type dbt) const override;
+
+    // helper for defining into vector<string>
+    std::size_t column_size(int position);
+
+    odbc_standard_into_type_backend * make_into_type_backend() override;
+    odbc_standard_use_type_backend * make_use_type_backend() override;
+    odbc_vector_into_type_backend * make_vector_into_type_backend() override;
+    odbc_vector_use_type_backend * make_vector_use_type_backend() override;
+
+    odbc_session_backend &session_;
+    SQLHSTMT hstmt_;
+    SQLULEN numRowsFetched_;
+    bool fetchVectorByRows_;
+    bool hasVectorUseElements_;
+    bool boundByName_;
+    bool boundByPos_;
+
+    long long rowsAffected_; // number of rows affected by the last operation
+
+    std::string query_;
+    std::vector<std::string> names_; // list of names for named binds
+
+    // This vector, containing non-owning non-null pointers, can be empty if
+    // we're not using any vector "intos".
+    std::vector<odbc_vector_into_type_backend*> intos_;
+
+private:
+    // fetch() helper wrapping SQLFetch() call for the given range of rows.
+    exec_fetch_result do_fetch(int beginRow, int endRow);
+};
+
+struct odbc_rowid_backend : details::rowid_backend
+{
+    odbc_rowid_backend(odbc_session_backend &session);
+
+    ~odbc_rowid_backend() override;
+};
+
+struct odbc_blob_backend : details::blob_backend
+{
+    odbc_blob_backend(odbc_session_backend &session);
+
+    ~odbc_blob_backend() override;
+
+    std::size_t get_len() override;
+    std::size_t read_from_start(void *buf, std::size_t toRead, std::size_t offset = 0) override;
+    std::size_t write_from_start(const void *buf, std::size_t toWrite, std::size_t offset = 0) override;
+    std::size_t append(const void *buf, std::size_t toWrite) override;
+    void trim(std::size_t newLen) override;
+
+    odbc_session_backend &session_;
+};
+
+struct odbc_session_backend : details::session_backend
+{
+    odbc_session_backend(connection_parameters const & parameters);
+
+    ~odbc_session_backend() override;
+
+    bool is_connected() override;
+
+    void begin() override;
+    void commit() override;
+    void rollback() override;
+
+    bool get_next_sequence_value(session & s,
+        std::string const & sequence, long long & value) override;
+    bool get_last_insert_id(session & s,
+        std::string const & table, long long & value) override;
+
+    std::string get_dummy_from_table() const override;
+
+    std::string get_backend_name() const override { return "odbc"; }
+
+    void configure_connection();
+    void reset_transaction();
+
+    void clean_up();
+
+    odbc_statement_backend * make_statement_backend() override;
+    odbc_rowid_backend * make_rowid_backend() override;
+    odbc_blob_backend * make_blob_backend() override;
+
+    enum database_product
+    {
+      prod_uninitialized, // Never returned by get_database_product().
+      prod_db2,
+      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.
+    SOCI_ODBC_DECL database_product get_database_product() const;
+
+    // Return full ODBC connection string.
+    std::string get_connection_string() const { return connection_string_; }
+
+    SQLHENV henv_;
+    SQLHDBC hdbc_;
+
+    std::string connection_string_;
+
+private:
+    mutable database_product product_;
+};
+
+class SOCI_ODBC_DECL odbc_soci_error : public soci_error
+{
+    SQLCHAR message_[SQL_MAX_MESSAGE_LENGTH + 1];
+    SQLCHAR sqlstate_[SQL_SQLSTATE_SIZE + 1];
+    SQLINTEGER sqlcode_;
+
+public:
+    odbc_soci_error(SQLSMALLINT htype,
+                  SQLHANDLE hndl,
+                  std::string const & msg)
+        : soci_error(interpret_odbc_error(htype, hndl, msg))
+    {
+    }
+
+    error_category get_error_category() const override
+    {
+        const char* const s = reinterpret_cast<const char*>(sqlstate_);
+
+        if ((s[0] == '0' && s[1] == '8') ||
+            strcmp(s, "HYT01") == 0)
+            return connection_error;
+
+        if (strcmp(s, "23000") == 0 ||
+            strcmp(s, "40002") == 0 ||
+            strcmp(s, "44000") == 0)
+            return constraint_violation;
+
+        if (strcmp(s, "HY014") == 0)
+            return system_error;
+
+        return unknown;
+    }
+
+    SQLCHAR const * odbc_error_code() const
+    {
+        return sqlstate_;
+    }
+    SQLINTEGER native_error_code() const
+    {
+        return sqlcode_;
+    }
+    SQLCHAR const * odbc_error_message() const
+    {
+        return message_;
+    }
+private:
+    std::string interpret_odbc_error(SQLSMALLINT htype, SQLHANDLE hndl, std::string const& msg)
+    {
+        const char* socierror = NULL;
+
+        SQLSMALLINT length, i = 1;
+        switch ( SQLGetDiagRecA(htype, hndl, i, sqlstate_, &sqlcode_,
+                               message_, SQL_MAX_MESSAGE_LENGTH + 1,
+                               &length) )
+        {
+          case SQL_SUCCESS:
+            // The error message was successfully retrieved.
+            break;
+
+          case SQL_INVALID_HANDLE:
+            socierror = "[SOCI]: Invalid handle.";
+            break;
+
+          case SQL_ERROR:
+            socierror = "[SOCI]: SQLGetDiagRec() error.";
+            break;
+
+          case SQL_SUCCESS_WITH_INFO:
+            socierror = "[SOCI]: Error message too long.";
+            break;
+
+          case SQL_NO_DATA:
+            socierror = "[SOCI]: No error.";
+            break;
+
+          default:
+            socierror = "[SOCI]: Unexpected SQLGetDiagRec() return value.";
+            break;
+        }
+
+        if (socierror)
+        {
+            // Use our own error message if we failed to retrieve the ODBC one.
+            strcpy(reinterpret_cast<char*>(message_), socierror);
+
+            // Use "General warning" SQLSTATE code.
+            strcpy(reinterpret_cast<char*>(sqlstate_), "01000");
+
+            sqlcode_ = 0;
+        }
+
+        std::ostringstream ss;
+        ss << "Error " << msg << ": " << message_ << " (SQL state " << sqlstate_ << ")";
+
+        return ss.str();
+    }
+};
+
+inline bool is_odbc_error(SQLRETURN rc)
+{
+    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA)
+    {
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+inline bool odbc_standard_type_backend_base::use_string_for_bigint() const
+{
+    // Oracle ODBC driver doesn't support SQL_C_[SU]BIGINT data types
+    // (see appendix G.1 of Oracle Database Administrator's reference at
+    // http://docs.oracle.com/cd/B19306_01/server.102/b15658/app_odbc.htm),
+    // so we need a special workaround for this case and we represent 64
+    // bit integers as strings and rely on ODBC driver for transforming
+    // them to SQL_NUMERIC.
+    return statement_.session_.get_database_product()
+            == odbc_session_backend::prod_oracle;
+}
+
+inline bool odbc_standard_type_backend_base::requires_noncompliant_32bit_sqllen() const
+{
+    // IBM DB2 did not implement the ODBC specification for indicator sizes in 64bit.
+    // They still use SQLLEN as 32bit even if the driver is compiled 64bit
+    // This breaks the backend in terms of using indicators
+    // see: https://bugs.php.net/bug.php?id=54007
+#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
+    return statement_.session_.get_database_product()
+            == odbc_session_backend::prod_db2;
+#else
+    return false;
+#endif
+}
+
+inline SQLLEN odbc_standard_type_backend_base::get_sqllen_from_value(const SQLLEN val) const
+{
+    if (requires_noncompliant_32bit_sqllen())
+    {
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#elif defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wstrict-aliasing"
+#endif
+        return *reinterpret_cast<const int*>(&val);
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#elif defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+    }
+    return val;
+}
+
+inline void odbc_standard_type_backend_base::set_sqllen_from_value(SQLLEN &target, const SQLLEN val) const
+{
+    if (requires_noncompliant_32bit_sqllen())
+    {
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#elif defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wstrict-aliasing"
+#endif
+        reinterpret_cast<int*>(&target)[0] =  *reinterpret_cast<const int*>(&val);
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#elif defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+    }
+    else
+    {
+        target = val;
+    }
+}
+
+inline bool odbc_standard_type_backend_base::supports_negative_tinyint() const
+{
+    // MSSQL ODBC driver only supports a range of [0..255] for tinyint.
+    return statement_.session_.get_database_product()
+            != odbc_session_backend::prod_mssql;
+}
+
+inline bool odbc_standard_type_backend_base::can_convert_to_unsigned_sql_type() const
+{
+    // MSSQL ODBC driver seemingly can't handle the conversion of unsigned C
+    // types to their respective unsigned SQL type because they are out of
+    // range for their supported signed types. This results in the error
+    // "Numeric value out of range (SQL state 22003)".
+    // The only place it works is with tinyint values as their range is
+    // [0..255], i.e. they have enough space for unsigned values anyway.
+    return statement_.session_.get_database_product()
+            != odbc_session_backend::prod_mssql;
+}
+
+inline SQLLEN odbc_vector_into_type_backend::get_sqllen_from_vector_at(std::size_t idx) const
+{
+    if (requires_noncompliant_32bit_sqllen())
+    {
+        return reinterpret_cast<const int*>(&indHolderVec_[0])[idx];
+    }
+    return indHolderVec_[idx];
+}
+
+inline void odbc_vector_use_type_backend::set_sqllen_from_vector_at(const std::size_t idx, const SQLLEN val)
+{
+    if (requires_noncompliant_32bit_sqllen())
+    {
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#elif defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wstrict-aliasing"
+#endif
+        reinterpret_cast<int*>(&indHolderVec_[0])[idx] = *reinterpret_cast<const int*>(&val);
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#elif defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+    }
+    else
+    {
+        indHolderVec_[idx] = val;
+    }
+}
+
+struct odbc_backend_factory : backend_factory
+{
+    odbc_backend_factory() {}
+    odbc_session_backend * make_session(
+        connection_parameters const & parameters) const override;
+};
+
+extern SOCI_ODBC_DECL odbc_backend_factory const odbc;
+
+extern "C"
+{
+
+// for dynamic backend loading
+SOCI_ODBC_DECL backend_factory const * factory_odbc();
+SOCI_ODBC_DECL void register_factory_odbc();
+
+} // extern "C"
+
+} // namespace soci
+
+#endif // SOCI_EMPTY_H_INCLUDED

+ 183 - 0
3rdparty/soci/include/soci/once-temp-type.h

@@ -0,0 +1,183 @@
+//
+// Copyright (C) 2004-2016 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_ONCE_TEMP_TYPE_H_INCLUDED
+#define SOCI_ONCE_TEMP_TYPE_H_INCLUDED
+
+#include "soci/soci-platform.h"
+#include "soci/ref-counted-statement.h"
+#include "soci/prepare-temp-type.h"
+
+namespace soci
+{
+
+class session;
+
+namespace details
+{
+
+class ref_counted_statement;
+
+// this needs to be lightweight and copyable
+class SOCI_DECL once_temp_type
+{
+public:
+
+    once_temp_type(session & s);
+    once_temp_type(once_temp_type const & o);
+    once_temp_type & operator=(once_temp_type const & o);
+
+    ~once_temp_type() noexcept(false);
+
+    template <typename T>
+    once_temp_type & operator<<(T const & t)
+    {
+        rcst_->accumulate(t);
+        return *this;
+    }
+
+    once_temp_type & operator,(into_type_ptr const &);
+    once_temp_type & operator,(use_type_ptr const &);
+
+    template <typename T, typename Indicator>
+    once_temp_type &operator,(into_container<T, Indicator> const &ic)
+    {
+        rcst_->exchange(ic);
+        return *this;
+    }
+    template <typename T, typename Indicator>
+    once_temp_type &operator,(use_container<T, Indicator> const &uc)
+    {
+        rcst_->exchange(uc);
+        return *this;
+    }
+
+private:
+    ref_counted_statement * rcst_;
+};
+
+// this needs to be lightweight and copyable
+class once_type
+{
+public:
+    once_type() : session_(NULL) {}
+    once_type(session * s) : session_(s) {}
+
+    void set_session(session * s)
+    {
+        session_ = s;
+    }
+
+    template <typename T>
+    once_temp_type operator<<(T const & t)
+    {
+        once_temp_type o(*session_);
+        o << t;
+        return o;
+    }
+
+private:
+    session * session_;
+};
+
+
+// this needs to be lightweight and copyable
+class prepare_type
+{
+public:
+    prepare_type() : session_(NULL) {}
+    prepare_type(session * s) : session_(s) {}
+
+    void set_session(session * s)
+    {
+        session_ = s;
+    }
+
+    template <typename T>
+    prepare_temp_type operator<<(T const & t)
+    {
+        prepare_temp_type p(*session_);
+        p << t;
+        return p;
+    }
+
+private:
+    session * session_;
+};
+
+} // namespace details
+
+// Note: ddl_type is intended to be used just as once_temp_type,
+// but since it can be also used directly (explicitly) by the user code,
+// it is declared outside of the namespace details.
+class SOCI_DECL ddl_type
+{
+public:
+
+    ddl_type(session & s);
+    ddl_type(const ddl_type & d);
+    ddl_type & operator=(const ddl_type & d);
+
+    ~ddl_type() noexcept(false);
+
+    void create_table(const std::string & tableName);
+    void add_column(const std::string & tableName,
+        const std::string & columnName, db_type dt,
+        int precision, int scale);
+    void alter_column(const std::string & tableName,
+        const std::string & columnName, db_type dt,
+        int precision, int scale);
+    void drop_column(const std::string & tableName,
+        const std::string & columnName);
+    ddl_type & column(const std::string & columnName, db_type dt,
+                      int precision = 0, int scale = 0);
+    ddl_type & unique(const std::string & name,
+        const std::string & columnNames);
+    ddl_type & primary_key(const std::string & name,
+        const std::string & columnNames);
+    ddl_type & foreign_key(const std::string & name,
+        const std::string & columnNames,
+        const std::string & refTableName,
+        const std::string & refColumnNames);
+
+    ddl_type & operator()(const std::string & arbitrarySql);
+
+    // helper function for handling delimiters
+    // between various parts of DDL statements
+    void set_tail(const std::string & tail);
+
+    // The functions below still work but are deprecated (but we don't give
+    // deprecation warnings for them because there is no real harm in using
+    // them).
+    //
+    // Use the overloads taking db_type instead in the new code.
+    void add_column(const std::string & tableName,
+        const std::string & columnName, data_type dt,
+        int precision, int scale)
+    {
+        add_column(tableName, columnName, details::to_db_type(dt), precision, scale);
+    }
+    void alter_column(const std::string & tableName,
+        const std::string & columnName, data_type dt,
+        int precision, int scale)
+    {
+        alter_column(tableName, columnName, details::to_db_type(dt), precision, scale);
+    }
+    ddl_type & column(const std::string & columnName, data_type dt,
+        int precision = 0, int scale = 0)
+    {
+        return column(columnName, details::to_db_type(dt), precision, scale);
+    }
+
+private:
+    session * s_;
+    details::ref_counted_statement * rcst_;
+};
+
+} // namespace soci
+
+#endif

+ 492 - 0
3rdparty/soci/include/soci/oracle/soci-oracle.h

@@ -0,0 +1,492 @@
+//
+// Copyright (C) 2004-2016 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_ORACLE_H_INCLUDED
+#define SOCI_ORACLE_H_INCLUDED
+
+#include <soci/soci-platform.h>
+
+#ifdef SOCI_ORACLE_SOURCE
+# define SOCI_ORACLE_DECL SOCI_DECL_EXPORT
+#else
+# define SOCI_ORACLE_DECL SOCI_DECL_IMPORT
+#endif
+
+#include <soci/soci-backend.h>
+#include <oci.h> // OCI
+#include <sstream>
+#include <vector>
+
+#ifdef _MSC_VER
+#pragma warning(disable:4512 4511)
+#endif
+
+
+namespace soci
+{
+
+class SOCI_ORACLE_DECL oracle_soci_error : public soci_error
+{
+public:
+    oracle_soci_error(std::string const & msg, int errNum = 0);
+
+    error_category get_error_category() const override { return cat_; }
+
+    int err_num_;
+    error_category cat_;
+};
+
+
+struct oracle_statement_backend;
+struct oracle_standard_into_type_backend : details::standard_into_type_backend
+{
+    oracle_standard_into_type_backend(oracle_statement_backend &st)
+        : statement_(st), defnp_(NULL), indOCIHolder_(0),
+          data_(NULL), buf_(NULL) {}
+
+    void define_by_pos(int &position,
+        void *data, details::exchange_type type) override;
+
+    void pre_exec(int num) override;
+    void pre_fetch() override;
+    void post_fetch(bool gotData, bool calledFromFetch,
+        indicator *ind) override;
+
+    void clean_up() override;
+
+    oracle_statement_backend &statement_;
+
+    OCIDefine *defnp_;
+    sb2 indOCIHolder_;
+    void *data_;
+    void *ociData_;
+    char *buf_;        // generic buffer
+    details::exchange_type type_;
+
+    ub2 rCode_;
+};
+
+struct oracle_vector_into_type_backend : details::vector_into_type_backend
+{
+    oracle_vector_into_type_backend(oracle_statement_backend &st)
+        : statement_(st), defnp_(NULL),
+        data_(NULL), buf_(NULL), user_ranges_(true) {}
+
+    void define_by_pos(int &position,
+        void *data, details::exchange_type type) override
+    {
+        user_ranges_ = false;
+        define_by_pos_bulk(position, data, type, 0, &end_var_);
+    }
+
+    void define_by_pos_bulk(
+        int & position, void * data, details::exchange_type type,
+        std::size_t begin, std::size_t * end) override;
+
+    void pre_exec(int num) override;
+    void pre_fetch() override;
+    void post_fetch(bool gotData, indicator *ind) override;
+
+    void resize(std::size_t sz) override;
+    std::size_t size() override;
+    std::size_t full_size();
+
+    void clean_up() override;
+
+    // helper function for preparing indicators and sizes_ vectors
+    // (as part of the define_by_pos)
+    void prepare_indicators(std::size_t size);
+
+    oracle_statement_backend &statement_;
+
+    OCIDefine *defnp_;
+    std::vector<sb2> indOCIHolderVec_;
+    void *data_;
+    char *buf_;              // generic buffer
+    details::exchange_type type_;
+    std::size_t begin_;
+    std::size_t * end_;
+    std::size_t end_var_;
+    bool user_ranges_;
+    std::size_t colSize_;    // size of the string column (used for strings)
+    std::vector<ub2> sizes_; // sizes of data fetched (used for strings)
+
+    std::vector<ub2> rCodes_;
+};
+
+struct oracle_standard_use_type_backend : details::standard_use_type_backend
+{
+    oracle_standard_use_type_backend(oracle_statement_backend &st)
+        : statement_(st), bindp_(NULL), indOCIHolder_(0),
+          data_(NULL), buf_(NULL) {}
+
+    void bind_by_pos(int &position,
+        void *data, details::exchange_type type, bool readOnly) override;
+    void bind_by_name(std::string const &name,
+        void *data, details::exchange_type type, bool readOnly) override;
+
+    // common part for bind_by_pos and bind_by_name
+    void prepare_for_bind(void *&data, sb4 &size, ub2 &oracleType, bool readOnly);
+
+    void pre_exec(int num) override;
+    void pre_use(indicator const *ind) override;
+    void post_use(bool gotData, indicator *ind) override;
+
+    void clean_up() override;
+
+    oracle_statement_backend &statement_;
+
+    OCIBind *bindp_;
+    sb2 indOCIHolder_;
+    void *data_;
+    void *ociData_;
+    bool readOnly_;
+    char *buf_;        // generic buffer
+    details::exchange_type type_;
+};
+
+struct oracle_vector_use_type_backend : details::vector_use_type_backend
+{
+    oracle_vector_use_type_backend(oracle_statement_backend &st)
+        : statement_(st), bindp_(NULL),
+          data_(NULL), buf_(NULL), bind_position_(0) {}
+
+    void bind_by_pos(int & position,
+        void * data, details::exchange_type type) override
+    {
+        bind_by_pos_bulk(position, data, type, 0, &end_var_);
+    }
+
+    void bind_by_pos_bulk(int & position,
+        void * data, details::exchange_type type,
+        std::size_t begin, std::size_t * end) override;
+
+    void bind_by_name(const std::string & name,
+        void * data, details::exchange_type type) override
+    {
+        bind_by_name_bulk(name, data, type, 0, &end_var_);
+    }
+
+    void bind_by_name_bulk(std::string const &name,
+        void *data, details::exchange_type type,
+        std::size_t begin, std::size_t * end) override;
+
+    // pre_use() helper
+    void prepare_for_bind(void *&data, sb4 &size, ub2 &oracleType);
+
+    // helper function for preparing indicators and sizes_ vectors
+    // (as part of the bind_by_pos and bind_by_name)
+    void prepare_indicators(std::size_t size);
+
+    void pre_use(indicator const *ind) override;
+
+    std::size_t size() override; // active size (might be lower than full vector size)
+    std::size_t full_size();    // actual size of the user-provided vector
+
+    void clean_up() override;
+
+    oracle_statement_backend &statement_;
+
+    OCIBind *bindp_;
+    std::vector<sb2> indOCIHolderVec_;
+    void *data_;
+    char *buf_;        // generic buffer
+    details::exchange_type type_;
+    std::size_t begin_;
+    std::size_t * end_;
+    std::size_t end_var_;
+
+    // used for strings only
+    std::vector<ub2> sizes_;
+    std::size_t maxSize_;
+
+    // name is used if non-empty, otherwise position
+    std::string bind_name_;
+    int bind_position_;
+};
+
+struct oracle_session_backend;
+struct oracle_statement_backend : details::statement_backend
+{
+    oracle_statement_backend(oracle_session_backend &session);
+
+    void alloc() override;
+    void clean_up() override;
+    void prepare(std::string const &query,
+        details::statement_type eType) override;
+
+    exec_fetch_result execute(int number) override;
+    exec_fetch_result fetch(int number) override;
+
+    long long get_affected_rows() override;
+    int get_number_of_rows() override;
+    std::string get_parameter_name(int index) const override;
+
+    std::string rewrite_for_procedure_call(std::string const &query) override;
+
+    int prepare_for_describe() override;
+    void describe_column(int colNum,
+        db_type &dbtype,
+        std::string &columnName) override;
+
+    // helper for defining into vector<string>
+    std::size_t column_size(int position);
+
+    oracle_standard_into_type_backend * make_into_type_backend() override;
+    oracle_standard_use_type_backend * make_use_type_backend() override;
+    oracle_vector_into_type_backend * make_vector_into_type_backend() override;
+    oracle_vector_use_type_backend * make_vector_use_type_backend() override;
+
+    oracle_session_backend &session_;
+
+    OCIStmt *stmtp_;
+
+    bool boundByName_;
+    bool boundByPos_;
+    bool noData_;
+};
+
+struct oracle_rowid_backend : details::rowid_backend
+{
+    oracle_rowid_backend(oracle_session_backend &session);
+
+    ~oracle_rowid_backend() override;
+
+    OCIRowid *rowidp_;
+};
+
+struct oracle_blob_backend : details::blob_backend
+{
+    typedef OCILobLocator * locator_t;
+
+    oracle_blob_backend(oracle_session_backend &session);
+
+    ~oracle_blob_backend() override;
+
+    std::size_t get_len() override;
+
+    std::size_t read_from_start(void * buf, std::size_t toRead, std::size_t offset = 0) override;
+
+    std::size_t write_from_start(const void * buf, std::size_t toWrite, std::size_t offset = 0) override;
+
+    std::size_t append(const void *buf, std::size_t toWrite) override;
+
+    void trim(std::size_t newLen) override;
+
+    locator_t get_lob_locator() const;
+
+    void set_lob_locator(locator_t locator, bool initialized = true);
+
+    void reset();
+
+    void ensure_initialized();
+
+private:
+    std::size_t do_deprecated_read(std::size_t offset, void *buf, std::size_t toRead) override
+    {
+        // Offsets are 1-based in Oracle
+        return read_from_start(buf, toRead, offset - 1);
+    }
+
+    std::size_t do_deprecated_write(std::size_t offset, const void *buf, std::size_t toWrite) override
+    {
+        // Offsets are 1-based in Oracle
+        return write_from_start(buf, toWrite, offset - 1);
+    }
+
+    oracle_session_backend &session_;
+
+    locator_t lobp_;
+
+    // If this is true, then the locator lobp_ points to something useful
+    // (instead of being the equivalent to a pointer with random value)
+    bool initialized_;
+};
+
+struct oracle_session_backend : details::session_backend
+{
+    oracle_session_backend(std::string const & serviceName,
+        std::string const & userName,
+        std::string const & password,
+        int mode,
+        bool decimals_as_strings = false,
+        int charset = 0,
+        int ncharset = 0);
+
+    ~oracle_session_backend() override;
+
+    bool is_connected() override;
+
+    void begin() override;
+    void commit() override;
+    void rollback() override;
+
+    std::string get_table_names_query() const override
+    {
+        return "select table_name"
+            " from user_tables";
+    }
+
+    std::string get_column_descriptions_query() const override
+    {
+        return "select column_name,"
+            " data_type,"
+            " char_length as character_maximum_length,"
+            " data_precision as numeric_precision,"
+            " data_scale as numeric_scale,"
+            " decode(nullable, 'Y', 'YES', 'N', 'NO') as is_nullable"
+            " from user_tab_columns"
+            " where table_name = :t";
+    }
+
+    std::string create_column_type(db_type dt,
+        int precision, int scale) override
+    {
+        //  Oracle-specific SQL syntax:
+
+        std::string res;
+        switch (dt)
+        {
+        case db_string:
+            {
+                std::ostringstream oss;
+
+                if (precision == 0)
+                {
+                    oss << "clob";
+                }
+                else
+                {
+                    oss << "varchar(" << precision << ")";
+                }
+
+                res += oss.str();
+            }
+            break;
+
+        case db_date:
+            res += "timestamp";
+            break;
+
+        case db_double:
+            {
+                std::ostringstream oss;
+                if (precision == 0)
+                {
+                    oss << "number";
+                }
+                else
+                {
+                    oss << "number(" << precision << ", " << scale << ")";
+                }
+
+                res += oss.str();
+            }
+            break;
+
+        case db_int16:
+            res += "smallint";
+            break;
+
+        case db_int32:
+            res += "integer";
+            break;
+
+        case db_int64:
+            res += "number";
+            break;
+
+        case db_uint64:
+            res += "number";
+            break;
+
+        case db_blob:
+            res += "blob";
+            break;
+
+        case db_xml:
+            res += "xmltype";
+            break;
+
+        default:
+            throw soci_error("this db_type is not supported in create_column");
+        }
+
+        return res;
+    }
+    std::string add_column(const std::string & tableName,
+        const std::string & columnName, db_type dt,
+        int precision, int scale) override
+    {
+        return "alter table " + tableName + " add " +
+            columnName + " " + create_column_type(dt, precision, scale);
+    }
+    std::string alter_column(const std::string & tableName,
+        const std::string & columnName, db_type dt,
+        int precision, int scale) override
+    {
+        return "alter table " + tableName + " modify " +
+            columnName + " " + create_column_type(dt, precision, scale);
+    }
+    std::string empty_blob() override
+    {
+        return "empty_blob()";
+    }
+    std::string nvl() override
+    {
+        return "nvl";
+    }
+
+    bool get_next_sequence_value(session &s,
+         std::string const &sequence, long long &value) override;
+
+    std::string get_dummy_from_table() const override { return "dual"; }
+
+    std::string get_backend_name() const override { return "oracle"; }
+
+    void clean_up();
+
+    oracle_statement_backend * make_statement_backend() override;
+    oracle_rowid_backend * make_rowid_backend() override;
+    oracle_blob_backend * make_blob_backend() override;
+
+    bool get_option_decimals_as_strings() { return decimals_as_strings_; }
+
+    // Return either SQLT_FLT or SQLT_BDOUBLE as the type to use when binding
+    // values of C type "double" (the latter is preferable but might not be
+    // always available).
+    ub2 get_double_sql_type() const;
+
+    OCIEnv *envhp_;
+    OCIServer *srvhp_;
+    OCIError *errhp_;
+    OCISvcCtx *svchp_;
+    OCISession *usrhp_;
+    bool decimals_as_strings_;
+};
+
+struct oracle_backend_factory : backend_factory
+{
+      oracle_backend_factory() {}
+    oracle_session_backend * make_session(
+        connection_parameters const & parameters) const override;
+};
+
+extern SOCI_ORACLE_DECL oracle_backend_factory const oracle;
+
+extern "C"
+{
+
+// for dynamic backend loading
+SOCI_ORACLE_DECL backend_factory const * factory_oracle();
+SOCI_ORACLE_DECL void register_factory_oracle();
+
+} // extern "C"
+
+} // namespace soci
+
+#endif

+ 442 - 0
3rdparty/soci/include/soci/postgresql/soci-postgresql.h

@@ -0,0 +1,442 @@
+//
+// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
+// Copyright (C) 2011 Gevorg Voskanyan
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_POSTGRESQL_H_INCLUDED
+#define SOCI_POSTGRESQL_H_INCLUDED
+
+#include <soci/soci-platform.h>
+
+#ifdef SOCI_POSTGRESQL_SOURCE
+# define SOCI_POSTGRESQL_DECL SOCI_DECL_EXPORT
+#else
+# define SOCI_POSTGRESQL_DECL SOCI_DECL_IMPORT
+#endif
+
+#include <soci/soci-backend.h>
+#include "soci/connection-parameters.h"
+#include <libpq-fe.h>
+#include <vector>
+#include <unordered_map>
+
+namespace soci
+{
+
+class SOCI_POSTGRESQL_DECL postgresql_soci_error : public soci_error
+{
+public:
+    postgresql_soci_error(std::string const & msg, char const * sqlst);
+
+    std::string sqlstate() const;
+
+    error_category get_error_category() const override { return cat_; }
+
+private:
+    char sqlstate_[ 5 ];   // not std::string to keep copy-constructor no-throw
+    error_category cat_;
+};
+
+struct postgresql_session_backend;
+
+namespace details
+{
+
+// A class thinly encapsulating PGresult. Its main purpose is to ensure that
+// PQclear() is always called, avoiding result memory leaks.
+class postgresql_result
+{
+public:
+    // Creates a wrapper for the given, possibly NULL, result. The wrapper
+    // object takes ownership of the result object and will call PQclear() on it.
+    explicit postgresql_result(
+        postgresql_session_backend & sessionBackend,
+        PGresult * result)
+        : sessionBackend_(sessionBackend)
+    {
+        init(result);
+    }
+
+    // Frees any currently stored result pointer and takes ownership of the
+    // given one.
+    void reset(PGresult* result = NULL)
+    {
+        clear();
+        init(result);
+    }
+
+    // Check whether the status is PGRES_COMMAND_OK and throw an exception if
+    // it is different. Notice that if the query can return any results,
+    // check_for_data() below should be used instead to verify whether anything
+    // was returned or not.
+    //
+    // The provided error message is used only for the exception being thrown
+    // and should describe the operation which yielded this result.
+    void check_for_errors(char const* errMsg) const;
+
+    // Check whether the status indicates successful query completion, either
+    // with the return results (in which case true is returned) or without them
+    // (then false is returned). If the status corresponds to an error, throws
+    // an exception, just as check_for_errors().
+    bool check_for_data(char const* errMsg) const;
+
+    // Implicit conversion to const PGresult: this is somewhat dangerous but
+    // allows us to avoid changing the existing code that uses PGresult and
+    // avoids the really bad problem with calling PQclear() twice accidentally
+    // as this would require a conversion to non-const pointer that we do not
+    // provide.
+    operator const PGresult*() const { return result_; }
+
+    // Get the associated result (which may be NULL). Unlike the implicit
+    // conversion above, this one returns a non-const pointer, so you should be
+    // careful to avoid really modifying it.
+    PGresult* get_result() const { return result_; }
+
+    // Dtor frees the result.
+    ~postgresql_result() { clear(); }
+
+private:
+    void init(PGresult* result)
+    {
+        result_ = result;
+    }
+
+    void clear()
+    {
+        // Notice that it is safe to call PQclear() with NULL pointer, it
+        // simply does nothing in this case.
+        PQclear(result_);
+    }
+
+    postgresql_session_backend & sessionBackend_;
+    PGresult* result_;
+
+    SOCI_NOT_COPYABLE(postgresql_result)
+};
+
+} // namespace details
+
+struct postgresql_statement_backend;
+struct postgresql_standard_into_type_backend : details::standard_into_type_backend
+{
+    postgresql_standard_into_type_backend(postgresql_statement_backend & st)
+        : statement_(st) {}
+
+    void define_by_pos(int & position,
+        void * data, details::exchange_type type) override;
+
+    void pre_fetch() override;
+    void post_fetch(bool gotData, bool calledFromFetch,
+        indicator * ind) override;
+
+    void clean_up() override;
+
+    postgresql_statement_backend & statement_;
+
+    void * data_;
+    details::exchange_type type_;
+    int position_;
+};
+
+struct postgresql_vector_into_type_backend : details::vector_into_type_backend
+{
+    postgresql_vector_into_type_backend(postgresql_statement_backend & st)
+        : statement_(st), user_ranges_(true) {}
+
+    void define_by_pos(int & position,
+        void * data, details::exchange_type type) override
+    {
+        user_ranges_ = false;
+        define_by_pos_bulk(position, data, type, 0, &end_var_);
+    }
+
+    void define_by_pos_bulk(int & position,
+        void * data, details::exchange_type type,
+        std::size_t begin, std::size_t * end) override;
+
+    void pre_fetch() override;
+    void post_fetch(bool gotData, indicator * ind) override;
+
+    void resize(std::size_t sz) override;
+    std::size_t size() override; // active size (might be lower than full vector size)
+    std::size_t full_size();    // actual size of the user-provided vector
+
+    void clean_up() override;
+
+    postgresql_statement_backend & statement_;
+
+    void * data_;
+    details::exchange_type type_;
+    std::size_t begin_;
+    std::size_t * end_;
+    std::size_t end_var_;
+    bool user_ranges_;
+    int position_;
+};
+
+struct postgresql_standard_use_type_backend : details::standard_use_type_backend
+{
+    postgresql_standard_use_type_backend(postgresql_statement_backend & st)
+        : statement_(st), position_(0), buf_(NULL) {}
+
+    void bind_by_pos(int & position,
+        void * data, details::exchange_type type, bool readOnly) override;
+    void bind_by_name(std::string const & name,
+        void * data, details::exchange_type type, bool readOnly) override;
+
+    void pre_use(indicator const * ind) override;
+    void post_use(bool gotData, indicator * ind) override;
+
+    void clean_up() override;
+
+    postgresql_statement_backend & statement_;
+
+    void * data_;
+    details::exchange_type type_;
+    int position_;
+    std::string name_;
+    char * buf_;
+
+private:
+    // Allocate buf_ of appropriate size and copy string data into it.
+    void copy_from_string(std::string const& s);
+};
+
+struct postgresql_vector_use_type_backend : details::vector_use_type_backend
+{
+    postgresql_vector_use_type_backend(postgresql_statement_backend & st)
+        : statement_(st), position_(0) {}
+
+    void bind_by_pos(int & position,
+        void * data, details::exchange_type type) override
+    {
+        bind_by_pos_bulk(position, data, type, 0, &end_var_);
+    }
+
+    void bind_by_pos_bulk(int & position,
+        void * data, details::exchange_type type,
+        std::size_t begin, std::size_t * end) override;
+
+    void bind_by_name(std::string const & name,
+        void * data, details::exchange_type type) override
+    {
+        bind_by_name_bulk(name, data, type, 0, &end_var_);
+    }
+
+    void bind_by_name_bulk(const std::string & name,
+        void * data, details::exchange_type type,
+        std::size_t begin, std::size_t * end) override;
+
+    void pre_use(indicator const * ind) override;
+
+    std::size_t size() override; // active size (might be lower than full vector size)
+    std::size_t full_size();    // actual size of the user-provided vector
+
+    void clean_up() override;
+
+    postgresql_statement_backend & statement_;
+
+    void * data_;
+    details::exchange_type type_;
+    std::size_t begin_;
+    std::size_t * end_;
+    std::size_t end_var_;
+    int position_;
+    std::string name_;
+    std::vector<char *> buffers_;
+};
+
+struct postgresql_statement_backend : details::statement_backend
+{
+    postgresql_statement_backend(postgresql_session_backend & session,
+        bool single_row_mode);
+    ~postgresql_statement_backend() override;
+
+    void alloc() override;
+    void clean_up() override;
+    void prepare(std::string const & query,
+        details::statement_type stType) override;
+
+    exec_fetch_result execute(int number) override;
+    exec_fetch_result fetch(int number) override;
+
+    long long get_affected_rows() override;
+    int get_number_of_rows() override;
+    std::string get_parameter_name(int index) const override;
+
+    std::string rewrite_for_procedure_call(std::string const & query) override;
+
+    int prepare_for_describe() override;
+    void describe_column(int colNum,
+        db_type & dbtype,
+        std::string & columnName) override;
+
+    postgresql_standard_into_type_backend * make_into_type_backend() override;
+    postgresql_standard_use_type_backend * make_use_type_backend() override;
+    postgresql_vector_into_type_backend * make_vector_into_type_backend() override;
+    postgresql_vector_use_type_backend * make_vector_use_type_backend() override;
+
+    postgresql_session_backend & session_;
+
+    bool single_row_mode_;
+
+    details::postgresql_result result_;
+    std::string query_;
+    details::statement_type stType_;
+    std::string statementName_;
+    std::vector<std::string> names_; // list of names for named binds
+
+    long long rowsAffectedBulk_; // number of rows affected by the last bulk operation
+
+    int numberOfRows_;  // number of rows retrieved from the server
+    int currentRow_;    // "current" row number to consume in postFetch
+    int rowsToConsume_; // number of rows to be consumed in postFetch
+
+    bool justDescribed_; // to optimize row description with immediately
+                         // following actual statement execution
+
+    bool hasIntoElements_;
+    bool hasVectorIntoElements_;
+    bool hasUseElements_;
+    bool hasVectorUseElements_;
+
+    // the following maps are used for finding data buffers according to
+    // use elements specified by the user
+
+    typedef std::map<int, char **> UseByPosBuffersMap;
+    UseByPosBuffersMap useByPosBuffers_;
+
+    typedef std::map<std::string, char **> UseByNameBuffersMap;
+    UseByNameBuffersMap useByNameBuffers_;
+
+    // the following map is used to keep the results of column
+    // type queries with custom types
+    typedef std::unordered_map<unsigned long, char> CategoryByColumnOID;
+    CategoryByColumnOID categoryByColumnOID_;
+};
+
+struct postgresql_rowid_backend : details::rowid_backend
+{
+    postgresql_rowid_backend(postgresql_session_backend & session);
+
+    ~postgresql_rowid_backend() override;
+
+    unsigned long value_;
+};
+
+class postgresql_blob_backend : public details::blob_backend
+{
+public:
+
+    struct blob_details
+    {
+        // OID of the large object
+        unsigned long oid;
+        // File descriptor of the large object
+        int fd;
+
+        blob_details();
+        blob_details(unsigned long oid, int fd);
+    };
+
+    postgresql_blob_backend(postgresql_session_backend & session);
+
+    ~postgresql_blob_backend() override;
+
+    std::size_t get_len() override;
+
+    std::size_t read_from_start(void * buf, std::size_t toRead, std::size_t offset = 0) override;
+
+    std::size_t write_from_start(const void * buf, std::size_t toWrite, std::size_t offset = 0) override;
+
+    std::size_t append(const void * buf, std::size_t toWrite) override;
+
+    void trim(std::size_t newLen) override;
+
+    const blob_details &get_blob_details() const;
+
+    void set_blob_details(const blob_details &details);
+
+    bool get_destroy_on_close() const;
+
+    void set_destroy_on_close(bool destroy);
+
+    void set_clone_before_modify(bool clone);
+
+    void init();
+
+    void reset();
+
+private:
+    postgresql_session_backend & session_;
+    blob_details details_;
+    bool destroy_on_close_;
+    bool clone_before_modify_;
+
+    std::size_t seek(std::size_t toOffset, int from);
+    void clone();
+};
+
+struct postgresql_session_backend : details::session_backend
+{
+    postgresql_session_backend(connection_parameters const & parameters,
+        bool single_row_mode);
+
+    ~postgresql_session_backend() override;
+
+    void connect(connection_parameters const & parameters);
+
+    bool is_connected() override;
+
+    void begin() override;
+    void commit() override;
+    void rollback() override;
+
+    void deallocate_prepared_statement(const std::string & statementName);
+
+    bool get_next_sequence_value(session & s,
+        std::string const & sequence, long long & value) override;
+
+    std::string get_dummy_from_table() const override { return std::string(); }
+
+    std::string get_backend_name() const override { return "postgresql"; }
+
+    void clean_up();
+
+    postgresql_statement_backend * make_statement_backend() override;
+    postgresql_rowid_backend * make_rowid_backend() override;
+    postgresql_blob_backend * make_blob_backend() override;
+
+    std::string get_next_statement_name();
+
+    int statementCount_;
+    bool single_row_mode_;
+    PGconn * conn_;
+    connection_parameters connectionParameters_;
+};
+
+
+struct postgresql_backend_factory : backend_factory
+{
+    postgresql_backend_factory() {}
+    postgresql_session_backend * make_session(
+        connection_parameters const & parameters) const override;
+};
+
+extern SOCI_POSTGRESQL_DECL postgresql_backend_factory const postgresql;
+
+extern "C"
+{
+
+// for dynamic backend loading
+SOCI_POSTGRESQL_DECL backend_factory const * factory_postgresql();
+SOCI_POSTGRESQL_DECL void register_factory_postgresql();
+
+} // extern "C"
+
+} // namespace soci
+
+#endif // SOCI_POSTGRESQL_H_INCLUDED

+ 65 - 0
3rdparty/soci/include/soci/prepare-temp-type.h

@@ -0,0 +1,65 @@
+//
+// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_PREPARE_TEMP_TYPE_INCLUDED
+#define SOCI_PREPARE_TEMP_TYPE_INCLUDED
+
+#include "soci/into-type.h"
+#include "soci/use-type.h"
+#include "soci/use.h"
+#include "soci/ref-counted-prepare-info.h"
+
+namespace soci
+{
+
+namespace details
+{
+
+// this needs to be lightweight and copyable
+class SOCI_DECL prepare_temp_type
+{
+public:
+    prepare_temp_type(session &);
+    prepare_temp_type(prepare_temp_type const &);
+    prepare_temp_type & operator=(prepare_temp_type const &);
+
+    ~prepare_temp_type();
+
+    template <typename T>
+    prepare_temp_type & operator<<(T const & t)
+    {
+        rcpi_->accumulate(t);
+        return *this;
+    }
+
+    prepare_temp_type & operator,(into_type_ptr const & i);
+
+    template <typename T, typename Indicator>
+    prepare_temp_type &operator,(into_container<T, Indicator> const &ic)
+    {
+        rcpi_->exchange(ic);
+        return *this;
+    }
+    template <typename T, typename Indicator>
+    prepare_temp_type &operator,(use_container<T, Indicator> const &uc)
+    {
+        rcpi_->exchange(uc);
+        return *this;
+    }
+
+    ref_counted_prepare_info * get_prepare_info() const { return rcpi_; }
+
+
+private:
+    ref_counted_prepare_info * rcpi_;
+};
+
+} // namespace details
+
+} // namespace soci
+
+#endif

+ 90 - 0
3rdparty/soci/include/soci/procedure.h

@@ -0,0 +1,90 @@
+//
+// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_PROCEDURE_H_INCLUDED
+#define SOCI_PROCEDURE_H_INCLUDED
+
+#include "soci/statement.h"
+
+namespace soci
+{
+
+namespace details
+{
+
+class SOCI_DECL procedure_impl : public statement_impl
+{
+public:
+    procedure_impl(session & s) : statement_impl(s), refCount_(1) {}
+    procedure_impl(prepare_temp_type const & prep);
+
+    void inc_ref() { ++refCount_; }
+    void dec_ref()
+    {
+        if (--refCount_ == 0)
+        {
+            delete this;
+        }
+    }
+
+private:
+    int refCount_;
+};
+
+} // namespace details
+
+class SOCI_DECL procedure
+{
+public:
+    // this is a conversion constructor
+    procedure(details::prepare_temp_type const & prep)
+        : impl_(new details::procedure_impl(prep)), gotData_(false) {}
+
+    ~procedure() { impl_->dec_ref(); }
+
+    // copy is supported here
+    procedure(procedure const & other)
+        : impl_(other.impl_), gotData_(other.gotData_)
+    {
+        impl_->inc_ref();
+    }
+    void operator=(procedure const & other)
+    {
+        other.impl_->inc_ref();
+        impl_->dec_ref();
+        impl_ = other.impl_;
+        gotData_ = other.gotData_;
+    }
+
+    // forwarders to procedure_impl
+    // (or rather to its base interface from statement_impl)
+
+    bool execute(bool withDataExchange = false)
+    {
+        gotData_ = impl_->execute(withDataExchange);
+        return gotData_;
+    }
+
+    bool fetch()
+    {
+        gotData_ = impl_->fetch();
+        return gotData_;
+    }
+
+    bool got_data() const
+    {
+        return gotData_;
+    }
+
+private:
+    details::procedure_impl * impl_;
+    bool gotData_;
+};
+
+} // namespace soci
+
+#endif

+ 57 - 0
3rdparty/soci/include/soci/query_transformation.h

@@ -0,0 +1,57 @@
+//
+// Copyright (C) 2013 Mateusz Loskot <mateusz@loskot.net>
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_QUERY_TRANSFORMATION_H_INCLUDED
+#define SOCI_QUERY_TRANSFORMATION_H_INCLUDED
+
+#include "soci/soci-platform.h"
+#include <string>
+
+namespace soci
+{
+
+namespace details
+{
+
+// Query transformation is a mechanism that enables user to apply
+// any string-to-string transformation to SQL statement just
+// before it is executed.
+// Transformation procedure is specified by user,
+// be it a function or an arbitrary type as long as it
+// defines operator() with the appropriate signature:
+// unary function takes any type converible-to std::string
+// and returns std::string.
+
+class query_transformation_function
+{
+public:
+    virtual ~query_transformation_function() {}
+    virtual std::string operator()(std::string const&) const = 0;
+};
+
+template <typename T>
+class query_transformation : public query_transformation_function
+{
+public:
+    query_transformation(T callback)
+        : callback_(callback)
+    {}
+
+    std::string operator()(std::string const& query) const override
+    {
+        return callback_(query);
+    }
+
+private:
+    T callback_;
+};
+
+} // namespace details
+
+} // namespace soci
+
+#endif // SOCI_QUERY_TRANSFORMATION_H_INCLUDED

+ 66 - 0
3rdparty/soci/include/soci/ref-counted-prepare-info.h

@@ -0,0 +1,66 @@
+//
+// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_REF_COUNTED_PREPARE_INFO_INCLUDED
+#define SOCI_REF_COUNTED_PREPARE_INFO_INCLUDED
+
+#include "soci/bind-values.h"
+#include "soci/ref-counted-statement.h"
+// std
+#include <string>
+#include <vector>
+
+namespace soci
+{
+
+class session;
+
+namespace details
+{
+
+class procedure_impl;
+class statement_impl;
+class into_type_base;
+
+// this class conveys only the statement text and the bind/define info
+// it exists only to be passed to statement's constructor
+class ref_counted_prepare_info : public ref_counted_statement_base
+{
+public:
+    ref_counted_prepare_info(session& s)
+        : ref_counted_statement_base(s)
+    {}
+
+    void exchange(use_type_ptr const& u) { uses_.exchange(u); }
+
+    template <typename T, typename Indicator>
+    void exchange(use_container<T, Indicator> const &uc)
+    { uses_.exchange(uc); }
+
+    void exchange(into_type_ptr const& i) { intos_.exchange(i); }
+
+    template <typename T, typename Indicator>
+    void exchange(into_container<T, Indicator> const &ic)
+    { intos_.exchange(ic); }
+
+    void final_action() override;
+
+private:
+    friend class statement_impl;
+    friend class procedure_impl;
+
+    into_type_vector intos_;
+    use_type_vector  uses_;
+
+    std::string get_query() const;
+};
+
+} // namespace details
+
+} // namespace soci
+
+#endif

+ 102 - 0
3rdparty/soci/include/soci/ref-counted-statement.h

@@ -0,0 +1,102 @@
+//
+// Copyright (C) 2004-2016 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_REF_COUNTED_STATEMENT_H_INCLUDED
+#define SOCI_REF_COUNTED_STATEMENT_H_INCLUDED
+
+#include "soci/statement.h"
+#include "soci/into-type.h"
+#include "soci/use-type.h"
+// std
+#include <sstream>
+
+namespace soci
+{
+
+namespace details
+{
+
+// this class is a base for both "once" and "prepare" statements
+class SOCI_DECL ref_counted_statement_base
+{
+public:
+    ref_counted_statement_base(session& s);
+
+    virtual ~ref_counted_statement_base() {}
+
+    virtual void final_action() = 0;
+
+    void inc_ref() { ++refCount_; }
+    void dec_ref()
+    {
+        if (--refCount_ == 0)
+        {
+            try
+            {
+                if (tail_.empty() == false)
+                {
+                    accumulate(tail_);
+                }
+
+                final_action();
+            }
+            catch (...)
+            {
+                delete this;
+                throw;
+            }
+
+            delete this;
+        }
+    }
+
+    template <typename T>
+    void accumulate(T const & t) { get_query_stream() << t; }
+
+    void set_tail(const std::string & tail) { tail_ = tail; }
+    void set_need_comma(bool need_comma) { need_comma_ = need_comma; }
+    bool get_need_comma() const { return need_comma_; }
+
+protected:
+    // this function allows to break the circular dependenc
+    // between session and this class
+    std::ostringstream & get_query_stream();
+
+    int refCount_;
+
+    session & session_;
+
+    // used mainly for portable ddl
+    std::string tail_;
+    bool need_comma_;
+
+private:
+    SOCI_NOT_COPYABLE(ref_counted_statement_base)
+};
+
+// this class is supposed to be a vehicle for the "once" statements
+// it executes the whole statement in its destructor
+class ref_counted_statement : public ref_counted_statement_base
+{
+public:
+    ref_counted_statement(session & s)
+        : ref_counted_statement_base(s), st_(s) {}
+
+    void final_action() override;
+
+    template <typename T>
+    void exchange(T &t) { st_.exchange(t); }
+
+private:
+    statement st_;
+};
+
+} // namespace details
+
+} // namespace soci
+
+#endif

+ 80 - 0
3rdparty/soci/include/soci/row-exchange.h

@@ -0,0 +1,80 @@
+//
+// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_INTO_ROW_H_INCLUDED
+#define SOCI_INTO_ROW_H_INCLUDED
+
+#include "soci/into-type.h"
+#include "soci/exchange-traits.h"
+#include "soci/row.h"
+#include "soci/statement.h"
+// std
+#include <cstddef>
+
+namespace soci
+{
+
+namespace details
+{
+
+// Support selecting into a row for dynamic queries
+
+template <>
+class into_type<row>
+    : public into_type_base // bypass the standard_into_type
+{
+public:
+    into_type(row & r) : r_(r) {}
+    into_type(row & r, indicator &) : r_(r) {}
+
+private:
+    // special handling for Row
+    void define(statement_impl & st, int & /* position */) override
+    {
+        st.set_row(&r_);
+
+        // actual row description is performed
+        // as part of the statement execute
+    }
+
+    void pre_exec(int /* num */) override {}
+    void pre_fetch() override {}
+    void post_fetch(bool gotData, bool /* calledFromFetch */) override
+    {
+        r_.reset_get_counter();
+
+        if (gotData)
+        {
+            // this is used only to re-dispatch to derived class, if any
+            // (the derived class might be generated automatically by
+            // user conversions)
+            convert_from_base();
+        }
+    }
+
+    void clean_up() override {}
+
+    std::size_t size() const override { return 1; }
+
+    virtual void convert_from_base() {}
+
+    row & r_;
+
+    SOCI_NOT_COPYABLE(into_type)
+};
+
+template <>
+struct exchange_traits<row>
+{
+    typedef basic_type_tag type_family;
+};
+
+} // namespace details
+
+} // namespace soci
+
+#endif

+ 202 - 0
3rdparty/soci/include/soci/row.h

@@ -0,0 +1,202 @@
+//
+// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_ROW_H_INCLUDED
+#define SOCI_ROW_H_INCLUDED
+
+#include "soci/type-holder.h"
+#include "soci/blob.h"
+#include "soci/type-conversion-traits.h"
+#include "soci/soci-backend.h"
+#include "soci/type-conversion.h"
+// std
+#include <cstddef>
+#include <map>
+#include <string>
+#include <vector>
+
+namespace soci
+{
+
+class SOCI_DECL column_properties
+{
+    // use getters/setters in case we want to make some
+    // of the getters lazy in the future
+public:
+
+    std::string get_name() const { return name_; }
+    // DEPRECATED. USE get_db_type() INSTEAD.
+    data_type get_data_type() const { return dataType_; }
+    db_type get_db_type() const { return dbType_; }
+
+    void set_name(std::string const& name) { name_ = name; }
+    // DEPRECATED. USE set_db_type(db_type) INSTEAD.
+    void set_data_type(data_type dataType)  { dataType_ = dataType; }
+    void set_db_type(db_type dataType)  { dbType_ = dataType; }
+
+private:
+    std::string name_;
+    // DEPRECATED. USE exchangeDataType_ INSTEAD.
+    data_type dataType_;
+    db_type dbType_;
+};
+
+class SOCI_DECL row
+{
+public:
+    row();
+    ~row();
+
+    row(row &&other) = default;
+    row &operator=(row &&other) = default;
+
+    void uppercase_column_names(bool forceToUpper);
+    void add_properties(column_properties const& cp);
+    std::size_t size() const;
+    void clean_up();
+
+    indicator get_indicator(std::size_t pos) const;
+    indicator get_indicator(std::string const& name) const;
+
+    template <typename T>
+    inline void add_holder(T* t, indicator* ind)
+    {
+        holders_.push_back(details::holder::make_holder(t));
+        indicators_.push_back(ind);
+    }
+
+    column_properties const& get_properties(std::size_t pos) const;
+    column_properties const& get_properties(std::string const& name) const;
+
+    template <typename T>
+    T get(std::size_t pos) const
+    {
+        typedef typename type_conversion<T>::base_type base_type;
+        static_assert(details::can_use_from_base<type_conversion<T>>(),
+                "Can't use row::get() with this type (not convertible/copy-assignable from base_type) - did you mean to use move_as?");
+        base_type const& baseVal =
+            holders_.at(pos)->get<base_type>(details::value_cast_tag{});
+
+        T ret;
+        type_conversion<T>::from_base(baseVal, *indicators_.at(pos), ret);
+        return ret;
+    }
+
+    template <typename T>
+    T move_as(std::size_t pos) const
+    {
+        typedef typename type_conversion<T>::base_type base_type;
+        static_assert(details::can_use_move_from_base<T, base_type>(),
+                "row::move_as() can only be called with types that can be instantiated from a base type rvalue reference");
+        base_type & baseVal =
+            holders_.at(pos)->get<base_type>(details::value_reference_tag{});
+
+        T ret;
+        type_conversion<T>::move_from_base(baseVal, *indicators_.at(pos), ret);
+        return ret;
+    }
+
+    template <typename T>
+    T get(std::size_t pos, T const &nullValue) const
+    {
+        if (i_null == *indicators_.at(pos))
+        {
+            return nullValue;
+        }
+
+        return get<T>(pos);
+    }
+
+    template <typename T>
+    T move_as(std::size_t pos, T const &nullValue) const
+    {
+        if (i_null == *indicators_.at(pos))
+        {
+            return nullValue;
+        }
+
+        return move_as<T>(pos);
+    }
+
+    template <typename T>
+    T get(std::string const &name) const
+    {
+        std::size_t const pos = find_column(name);
+        return get<T>(pos);
+    }
+
+    template <typename T>
+    T move_as(std::string const &name) const
+    {
+        std::size_t const pos = find_column(name);
+        return move_as<T>(pos);
+    }
+
+    template <typename T>
+    T get(std::string const &name, T const &nullValue) const
+    {
+        std::size_t const pos = find_column(name);
+
+        if (i_null == *indicators_[pos])
+        {
+            return nullValue;
+        }
+
+        return get<T>(pos);
+    }
+
+    template <typename T>
+    T move_as(std::string const &name, T const &nullValue) const
+    {
+        std::size_t const pos = find_column(name);
+
+        if (i_null == *indicators_[pos])
+        {
+            return nullValue;
+        }
+
+        return move_as<T>(pos);
+    }
+
+    template <typename T>
+    row const& operator>>(T& value) const
+    {
+        value = get<T>(currentPos_);
+        ++currentPos_;
+        return *this;
+    }
+
+    void skip(std::size_t num = 1) const
+    {
+        currentPos_ += num;
+    }
+
+    void reset_get_counter() const
+    {
+        currentPos_ = 0;
+    }
+
+private:
+    SOCI_NOT_COPYABLE(row)
+
+    std::size_t find_column(std::string const& name) const;
+
+    std::vector<column_properties> columns_;
+    std::vector<details::holder*> holders_;
+    std::vector<indicator*> indicators_;
+    std::map<std::string, std::size_t> index_;
+
+    bool uppercaseColumnNames_;
+    mutable std::size_t currentPos_;
+};
+
+template <>
+blob SOCI_DECL row::move_as<blob>(std::size_t pos) const;
+
+} // namespace soci
+
+#endif // SOCI_ROW_H_INCLUDED

+ 59 - 0
3rdparty/soci/include/soci/rowid-exchange.h

@@ -0,0 +1,59 @@
+//
+// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_ROWID_EXCHANGE_H_INCLUDED
+#define SOCI_ROWID_EXCHANGE_H_INCLUDED
+
+#include "soci/rowid.h"
+#include "soci/into-type.h"
+#include "soci/use-type.h"
+#include "soci/exchange-traits.h"
+// std
+#include <string>
+
+namespace soci
+{
+
+namespace details
+{
+
+template <>
+class use_type<rowid> : public standard_use_type
+{
+public:
+    use_type(rowid & rid, std::string const & name = std::string())
+        : standard_use_type(&rid, x_rowid, false, name) {}
+    use_type(rowid const & rid, std::string const & name = std::string())
+        : standard_use_type(const_cast<rowid *>(&rid), x_rowid, true, name) {}
+    use_type(rowid & rid, indicator & ind,
+        std::string const & name = std::string())
+        : standard_use_type(&rid, x_rowid, ind, false, name) {}
+    use_type(rowid const & rid, indicator & ind,
+        std::string const & name = std::string())
+        : standard_use_type(const_cast<rowid *>(&rid), x_rowid, ind, true, name) {}
+};
+
+template <>
+class into_type<rowid> : public standard_into_type
+{
+public:
+    into_type(rowid & rid) : standard_into_type(&rid, x_rowid) {}
+    into_type(rowid & rid, indicator & ind)
+        :standard_into_type(&rid, x_rowid, ind) {}
+};
+
+template <>
+struct exchange_traits<soci::rowid>
+{
+    typedef basic_type_tag type_family;
+};
+
+} // namespace details
+
+} // namespace soci
+
+#endif // SOCI_ROWID_EXCHANGE_H_INCLUDED

+ 41 - 0
3rdparty/soci/include/soci/rowid.h

@@ -0,0 +1,41 @@
+//
+// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_ROWID_H_INCLUDED
+#define SOCI_ROWID_H_INCLUDED
+
+#include "soci/soci-platform.h"
+
+namespace soci
+{
+
+class session;
+
+namespace details
+{
+
+class rowid_backend;
+
+} // namespace details
+
+// ROWID support
+
+class SOCI_DECL rowid
+{
+public:
+    explicit rowid(session & s);
+    ~rowid();
+
+    details::rowid_backend * get_backend() { return backEnd_; }
+
+private:
+    details::rowid_backend *backEnd_;
+};
+
+} // namespace soci
+
+#endif

+ 241 - 0
3rdparty/soci/include/soci/rowset.h

@@ -0,0 +1,241 @@
+//
+// Copyright (C) 2006-2008 Mateusz Loskot
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_ROWSET_H_INCLUDED
+#define SOCI_ROWSET_H_INCLUDED
+
+#include "soci/soci-platform.h"
+#include "soci/statement.h"
+// std
+#include <iterator>
+#include <memory>
+
+namespace soci
+{
+
+//
+// rowset iterator of input category.
+//
+template <typename T>
+class rowset_iterator
+{
+public:
+
+    // Standard iterator traits
+
+    typedef std::input_iterator_tag iterator_category;
+    typedef T   value_type;
+    typedef T * pointer;
+    typedef T & reference;
+    typedef ptrdiff_t difference_type;
+
+    // Constructors
+
+    rowset_iterator()
+        : st_(0), define_(0)
+    {}
+
+    rowset_iterator(statement & st, T & define)
+        : st_(&st), define_(&define)
+    {
+        // Fetch first row to properly initialize iterator
+        ++(*this);
+    }
+
+    // Access operators
+
+    reference operator*() const
+    {
+        return (*define_);
+    }
+
+    pointer operator->() const
+    {
+        return &(operator*());
+    }
+
+    // Iteration operators
+
+    rowset_iterator & operator++()
+    {
+        // Fetch next row from dataset
+
+        if (st_->fetch() == false)
+        {
+            // Set iterator to non-derefencable state (pass-the-end)
+            st_ = 0;
+            define_ = 0;
+        }
+
+        return (*this);
+    }
+
+    rowset_iterator operator++(int)
+    {
+        rowset_iterator tmp(*this);
+        ++(*this);
+        return tmp;
+    }
+
+    // Comparison operators
+
+    bool operator==(rowset_iterator const & rhs) const
+    {
+        return (st_== rhs.st_ && define_ == rhs.define_);
+    }
+
+    bool operator!=(rowset_iterator const & rhs) const
+    {
+        return ((*this == rhs) == false);
+    }
+
+private:
+
+    statement * st_;
+    T * define_;
+
+}; // class rowset_iterator
+
+namespace details
+{
+
+//
+// Implementation of rowset
+//
+template <typename T>
+class rowset_impl
+{
+public:
+
+    typedef rowset_iterator<T> iterator;
+
+    rowset_impl()
+        : refs_(1), st_(nullptr), define_(nullptr)
+    {
+    }
+
+    rowset_impl(details::prepare_temp_type const & prep)
+        : refs_(1), st_(new statement(prep)), define_(new T())
+    {
+        st_->exchange_for_rowset(into(*define_));
+        st_->execute();
+    }
+
+    void incRef()
+    {
+        ++refs_;
+    }
+
+    void decRef()
+    {
+        if (--refs_ == 0)
+        {
+            delete this;
+        }
+    }
+
+    iterator begin() const
+    {
+        // No ownership transfer occurs here. Empty rowset doesn't have any valid begin iterator.
+        return st_ ? iterator(*st_, *define_) : iterator();
+    }
+
+    iterator end() const
+    {
+        return iterator();
+    }
+
+private:
+
+    unsigned int refs_;
+
+    const std::unique_ptr<statement> st_;
+    const std::unique_ptr<T> define_;
+    SOCI_NOT_COPYABLE(rowset_impl)
+}; // class rowset_impl
+
+} // namespace details
+
+
+//
+// rowset is a thin wrapper on statement and provides access to STL-like input iterator.
+// The rowset_iterator can be used to easily loop through statement results and
+// use STL algorithms accepting input iterators.
+//
+template <typename T = soci::row>
+class rowset
+{
+public:
+
+    typedef T value_type;
+    typedef rowset_iterator<T> iterator;
+    typedef rowset_iterator<T> const_iterator;
+
+    // this is a conversion constructor
+    rowset(details::prepare_temp_type const& prep)
+        : pimpl_(new details::rowset_impl<T>(prep))
+    {
+    }
+
+    rowset(rowset const & other)
+        : pimpl_(other.pimpl_)
+    {
+        pimpl_->incRef();
+    }
+
+    rowset()
+       : pimpl_(new details::rowset_impl<T>())
+    {
+    }
+
+    // Due to the existence of conversion from session to prepare_temp_type, it
+    // would have been possible to construct a rowset from session if we didn't
+    // delete this ctor -- so do delete it because it doesn't make sense to
+    // provide such constructor.
+    rowset(session const& session) = delete;
+
+    ~rowset()
+    {
+        pimpl_->decRef();
+    }
+
+    rowset& operator=(rowset const& rhs)
+    {
+        if (&rhs != this)
+        {
+            rhs.pimpl_->incRef();
+            pimpl_->decRef();
+            pimpl_ = rhs.pimpl_;
+        }
+        return *this;
+    }
+
+    void clear()
+    {
+        *this = rowset();
+    }
+
+    const_iterator begin() const
+    {
+        return pimpl_->begin();
+    }
+
+    const_iterator end() const
+    {
+        return pimpl_->end();
+    }
+
+private:
+
+    // Pointer to implementation - the body
+    details::rowset_impl<T>* pimpl_;
+
+}; // class rowset
+
+} // namespace soci
+
+#endif // SOCI_ROWSET_H_INCLUDED

+ 239 - 0
3rdparty/soci/include/soci/session.h

@@ -0,0 +1,239 @@
+//
+// Copyright (C) 2004-2016 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_SESSION_H_INCLUDED
+#define SOCI_SESSION_H_INCLUDED
+
+#include "soci/soci-platform.h"
+#include "soci/once-temp-type.h"
+#include "soci/query_transformation.h"
+#include "soci/connection-parameters.h"
+#include "soci/logger.h"
+
+// std
+#include <cstddef>
+#include <memory>
+#include <ostream>
+#include <sstream>
+#include <string>
+
+namespace soci
+{
+class values;
+class backend_factory;
+
+namespace details
+{
+
+class session_backend;
+class statement_backend;
+class rowid_backend;
+class blob_backend;
+
+} // namespace details
+
+class connection_pool;
+class failover_callback;
+
+class SOCI_DECL session
+{
+private:
+
+    void set_query_transformation_(std::unique_ptr<details::query_transformation_function>&& qtf);
+
+
+
+public:
+    session();
+    explicit session(connection_parameters const & parameters);
+    session(backend_factory const & factory, std::string const & connectString);
+    session(std::string const & backendName, std::string const & connectString);
+    explicit session(std::string const & connectString);
+    explicit session(connection_pool & pool);
+
+    session(session &&other);
+    session &operator=(session &&other);
+
+    ~session();
+
+    void open(connection_parameters const & parameters);
+    void open(backend_factory const & factory, std::string const & connectString);
+    void open(std::string const & backendName, std::string const & connectString);
+    void open(std::string const & connectString);
+    void close();
+    void reconnect();
+
+    // check if we have a working connection to the database
+    bool is_connected() const noexcept;
+
+    void begin();
+    void commit();
+    void rollback();
+
+    // once and prepare are for syntax sugar only
+    details::once_type once;
+    details::prepare_type prepare;
+
+    // even more sugar
+    template <typename T>
+    details::once_temp_type operator<<(T const & t) { return once << t; }
+
+    std::ostringstream & get_query_stream();
+    std::string get_query() const;
+
+    template <typename T>
+    void set_query_transformation(T callback)
+    {
+        set_query_transformation_(std::make_unique<details::query_transformation<T>>(callback));
+    }
+
+    // Support for custom logging of database operations.
+
+    // Set the custom logger to use.
+    void set_logger(logger const & logger);
+
+    // Return the currently used logger, by default, this is an instance of a
+    // standard SOCI logger.
+    logger const & get_logger() const;
+
+
+    // support for basic logging (use set_logger() for more control).
+    void set_log_stream(std::ostream * s);
+    std::ostream * get_log_stream() const;
+
+    void log_query(std::string const & query);
+    std::string get_last_query() const;
+
+    void set_got_data(bool gotData);
+    bool got_data() const;
+
+    void uppercase_column_names(bool forceToUpper);
+
+    bool get_uppercase_column_names() const;
+
+    // Functions for dealing with sequence/auto-increment values.
+
+    // If true is returned, value is filled with the next value from the given
+    // sequence. Otherwise either the sequence is invalid (doesn't exist) or
+    // the current backend doesn't support sequences. If you use sequences for
+    // automatically generating primary key values, you should use
+    // get_last_insert_id() after the insertion in this case.
+    bool get_next_sequence_value(std::string const & sequence, long long & value);
+
+    // If true is returned, value is filled with the last auto-generated value
+    // for this table (although some backends ignore the table argument and
+    // return the last value auto-generated in this session).
+    bool get_last_insert_id(std::string const & table, long long & value);
+
+    // Returns once_temp_type for the internally composed query
+    // for the list of tables in the current schema.
+    // Since this query usually returns multiple results (for multiple tables),
+    // it makes sense to bind std::vector<std::string> for the single output field.
+    details::once_temp_type get_table_names();
+
+    // Returns prepare_temp_type for the internally composed query
+    // for the list of tables in the current schema.
+    // Since this is intended for use with statement objects, where results are obtained one row after another,
+    // it makes sense to bind std::string for the output field.
+    details::prepare_temp_type prepare_table_names();
+
+    // Returns prepare_temp_type for the internally composed query
+    // for the list of column descriptions.
+    // Since this is intended for use with statement objects, where results are obtained one row after another,
+    // it makes sense to bind either std::string for each output field or soci::column_info for the whole row.
+    // Note: table_name is a non-const reference to prevent temporary objects,
+    // this argument is bound as a regular "use" element.
+    details::prepare_temp_type prepare_column_descriptions(std::string & table_name);
+
+    // Functions for basic portable DDL statements.
+
+    ddl_type create_table(const std::string & tableName);
+    void drop_table(const std::string & tableName);
+    void truncate_table(const std::string & tableName);
+    ddl_type add_column(const std::string & tableName,
+        const std::string & columnName, db_type dt,
+        int precision = 0, int scale = 0);
+    ddl_type alter_column(const std::string & tableName,
+        const std::string & columnName, db_type dt,
+        int precision = 0, int scale = 0);
+    ddl_type drop_column(const std::string & tableName,
+        const std::string & columnName);
+    std::string empty_blob();
+    std::string nvl();
+
+    // And some functions to help with writing portable DML statements.
+
+    // Get the name of the dummy table that needs to be used in the FROM clause
+    // of a SELECT statement not operating on any tables, e.g. "dual" for
+    // Oracle. The returned string is empty if no such table is needed.
+    std::string get_dummy_from_table() const;
+
+    // Returns a possibly empty string that needs to be used as a FROM clause
+    // of a SELECT statement not operating on any tables, e.g. " FROM DUAL"
+    // (notice the leading space).
+    std::string get_dummy_from_clause() const;
+
+
+    // Sets the failover callback object.
+    void set_failover_callback(failover_callback & callback);
+
+    // for diagnostics and advanced users
+    // (downcast it to expected back-end session class)
+    details::session_backend * get_backend() { return backEnd_; }
+
+    std::string get_backend_name() const;
+
+    // The functions below still work but are deprecated (but we don't give
+    // deprecation warnings for them because there is no real harm in using
+    // them).
+    //
+    // Use the overloads taking db_type instead in the new code.
+    ddl_type add_column(const std::string & tableName,
+        const std::string & columnName, data_type dt,
+        int precision = 0, int scale = 0)
+    {
+        return add_column(tableName, columnName, details::to_db_type(dt),
+            precision, scale);
+    }
+    ddl_type alter_column(const std::string & tableName,
+        const std::string & columnName, data_type dt,
+        int precision = 0, int scale = 0)
+    {
+        return alter_column(tableName, columnName, details::to_db_type(dt),
+            precision, scale);
+    }
+
+    details::statement_backend * make_statement_backend();
+    details::rowid_backend * make_rowid_backend();
+    details::blob_backend * make_blob_backend();
+
+private:
+    SOCI_NOT_COPYABLE(session)
+
+    void reset_after_move();
+
+    std::ostringstream query_stream_;
+    std::unique_ptr<details::query_transformation_function> query_transformation_;
+
+    logger logger_;
+
+    connection_parameters lastConnectParameters_;
+
+    bool uppercaseColumnNames_;
+
+    details::session_backend * backEnd_;
+
+    bool gotData_;
+
+    bool isFromPool_;
+    std::size_t poolPosition_;
+    connection_pool * pool_;
+};
+
+} // namespace soci
+
+#endif // SOCI_SESSION_H_INCLUDED

+ 591 - 0
3rdparty/soci/include/soci/soci-backend.h

@@ -0,0 +1,591 @@
+//
+// Copyright (C) 2004-2016 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_BACKEND_H_INCLUDED
+#define SOCI_BACKEND_H_INCLUDED
+
+#include "soci/soci-platform.h"
+#include "soci/error.h"
+// std
+#include <cstddef>
+#include <map>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <algorithm>
+#include <cstring>
+
+namespace soci
+{
+
+// data types, as seen by the user
+enum db_type
+{
+    db_string,
+    db_int8,
+    db_uint8,
+    db_int16,
+    db_uint16,
+    db_int32,
+    db_uint32,
+    db_int64,
+    db_uint64,
+    db_double,
+    db_date,
+    db_blob,
+    db_xml
+};
+
+// DEPRECATED. USE db_type INSTEAD.
+enum data_type
+{
+    dt_string, dt_date, dt_double, dt_integer, dt_long_long, dt_unsigned_long_long,
+    dt_blob, dt_xml
+};
+
+// the enum type for indicator variables
+enum indicator { i_ok, i_null, i_truncated };
+
+class session;
+class failover_callback;
+
+namespace details
+{
+
+// data types, as used to describe exchange format
+enum exchange_type
+{
+    x_char,
+    x_stdstring,
+    x_int8,
+    x_uint8,
+    x_int16,
+    x_uint16,
+    x_int32,
+    x_uint32,
+    x_int64,
+    x_uint64,
+    x_double,
+    x_stdtm,
+    x_statement,
+    x_rowid,
+    x_blob,
+
+    x_xmltype,
+    x_longstring,
+
+    // Deprecated synonyms.
+    x_short = x_int16,
+    x_integer = x_int32,
+    x_long_long = x_int64,
+    x_unsigned_long_long = x_uint64
+};
+
+// type of statement (used for optimizing statement preparation)
+enum statement_type
+{
+    st_one_time_query,
+    st_repeatable_query
+};
+
+// (lossless) conversion from the legacy data type enum
+inline db_type to_db_type(data_type dt)
+{
+    switch (dt)
+    {
+        case dt_string:             return db_string;
+        case dt_date:               return db_date;
+        case dt_double:             return db_double;
+        case dt_integer:            return db_int32;
+        case dt_long_long:          return db_int64;
+        case dt_unsigned_long_long: return db_uint64;
+        case dt_blob:               return db_blob;
+        case dt_xml:                return db_xml;
+    }
+
+    // unreachable
+    return db_string;
+}
+
+// polymorphic into type backend
+
+class standard_into_type_backend
+{
+public:
+    standard_into_type_backend() {}
+    virtual ~standard_into_type_backend() {}
+
+    virtual void define_by_pos(int& position, void* data, exchange_type type) = 0;
+
+    virtual void pre_exec(int /* num */) {}
+    virtual void pre_fetch() = 0;
+    virtual void post_fetch(bool gotData, bool calledFromFetch, indicator* ind) = 0;
+
+    virtual void clean_up() = 0;
+
+private:
+    SOCI_NOT_COPYABLE(standard_into_type_backend)
+};
+
+class vector_into_type_backend
+{
+public:
+
+    vector_into_type_backend() {}
+    virtual ~vector_into_type_backend() {}
+
+    virtual void define_by_pos_bulk(
+        int & /* position */, void * /* data */, exchange_type /* type */,
+        std::size_t /* begin */, std::size_t * /* end */)
+    {
+        throw soci_error("into bulk iterators are not supported with this backend");
+    }
+
+    virtual void define_by_pos(int& position, void* data, exchange_type type) = 0;
+
+    virtual void pre_exec(int /* num */) {}
+    virtual void pre_fetch() = 0;
+    virtual void post_fetch(bool gotData, indicator* ind) = 0;
+
+    virtual void resize(std::size_t sz) = 0;
+    virtual std::size_t size() = 0;
+
+    virtual void clean_up() = 0;
+
+private:
+    SOCI_NOT_COPYABLE(vector_into_type_backend)
+};
+
+// polymorphic use type backend
+
+class standard_use_type_backend
+{
+public:
+    standard_use_type_backend() {}
+    virtual ~standard_use_type_backend() {}
+
+    virtual void bind_by_pos(int& position, void* data,
+        exchange_type type, bool readOnly) = 0;
+    virtual void bind_by_name(std::string const& name,
+        void* data, exchange_type type, bool readOnly) = 0;
+
+    virtual void pre_exec(int /* num */) {}
+    virtual void pre_use(indicator const* ind) = 0;
+    virtual void post_use(bool gotData, indicator * ind) = 0;
+
+    virtual void clean_up() = 0;
+
+private:
+    SOCI_NOT_COPYABLE(standard_use_type_backend)
+};
+
+class vector_use_type_backend
+{
+public:
+    vector_use_type_backend() {}
+    virtual ~vector_use_type_backend() {}
+
+    virtual void bind_by_pos(int& position, void* data, exchange_type type) = 0;
+    virtual void bind_by_pos_bulk(int& /* position */, void* /* data */, exchange_type /* type */,
+        std::size_t /* begin */, std::size_t * /* end */)
+    {
+        throw soci_error("using bulk iterators are not supported with this backend");
+    }
+
+    virtual void bind_by_name(std::string const& name,
+        void* data, exchange_type type) = 0;
+
+    virtual void bind_by_name_bulk(std::string const& /* name */,
+        void* /* data */, exchange_type /* type */,
+        std::size_t /* begin */, std::size_t * /* end */)
+    {
+        throw soci_error("using bulk iterators are not supported with this backend");
+    }
+
+    virtual void pre_exec(int /* num */) {}
+    virtual void pre_use(indicator const* ind) = 0;
+
+    virtual std::size_t size() = 0;
+
+    virtual void clean_up() = 0;
+
+private:
+    SOCI_NOT_COPYABLE(vector_use_type_backend)
+};
+
+// polymorphic statement backend
+
+class statement_backend
+{
+public:
+    statement_backend() {}
+    virtual ~statement_backend() {}
+
+    virtual void alloc() = 0;
+    virtual void clean_up() = 0;
+
+    virtual void prepare(std::string const& query, statement_type eType) = 0;
+
+    enum exec_fetch_result
+    {
+        ef_success,
+        ef_no_data
+    };
+
+    virtual exec_fetch_result execute(int number) = 0;
+    virtual exec_fetch_result fetch(int number) = 0;
+
+    virtual long long get_affected_rows() = 0;
+    virtual int get_number_of_rows() = 0;
+
+    virtual std::string get_parameter_name(int index) const = 0;
+
+    virtual std::string rewrite_for_procedure_call(std::string const& query) = 0;
+
+    virtual int prepare_for_describe() = 0;
+    virtual void describe_column(int colNum,
+        db_type& dbtype,
+        std::string& column_name) = 0;
+
+    // Function converting db_type to legacy data_type: this is mostly, but not
+    // quite, backend-independent because different backends handled the same
+    // type differently before db_type introduction.
+    virtual data_type to_data_type(db_type dbt) const
+    {
+        switch (dbt)
+        {
+            case db_string: return dt_string;
+            case db_date:   return dt_date;
+            case db_double: return dt_double;
+            case db_int8:
+            case db_uint8:
+            case db_int16:
+            case db_uint16:
+            case db_int32:  return dt_integer;
+            case db_uint32:
+            case db_int64:  return dt_long_long;
+            case db_uint64: return dt_unsigned_long_long;
+            case db_blob:   return dt_blob;
+            case db_xml:    return dt_xml;
+        }
+
+        // unreachable
+        return dt_string;
+    }
+
+    virtual standard_into_type_backend* make_into_type_backend() = 0;
+    virtual standard_use_type_backend* make_use_type_backend() = 0;
+    virtual vector_into_type_backend* make_vector_into_type_backend() = 0;
+    virtual vector_use_type_backend* make_vector_use_type_backend() = 0;
+
+private:
+    SOCI_NOT_COPYABLE(statement_backend)
+};
+
+// polymorphic RowID backend
+
+class rowid_backend
+{
+public:
+    virtual ~rowid_backend() {}
+};
+
+// polymorphic blob backend
+
+class blob_backend
+{
+public:
+    blob_backend() {}
+    virtual ~blob_backend() {}
+
+    virtual std::size_t get_len() = 0;
+
+    virtual std::size_t read_from_start(void* buf, std::size_t toRead, std::size_t offset) = 0;
+
+    virtual std::size_t write_from_start(const void* buf, std::size_t toWrite, std::size_t offset) = 0;
+
+    virtual std::size_t append(const void* buf, std::size_t toWrite) = 0;
+
+    virtual void trim(std::size_t newLen) = 0;
+
+    // Deprecated functions with backend-specific semantics preserved only for
+    // compatibility.
+    [[deprecated("Use read_from_start instead")]]
+    std::size_t read(std::size_t offset, void* buf, std::size_t toRead) { return do_deprecated_read(offset, buf, toRead); }
+
+    [[deprecated("Use write_from_start instead")]]
+    virtual std::size_t write(std::size_t offset, const void* buf, std::size_t toWrite) { return do_deprecated_write(offset, buf, toWrite); }
+
+private:
+    virtual std::size_t do_deprecated_read(std::size_t offset, void* buf, std::size_t toRead) { return read_from_start(buf, toRead, offset); }
+    virtual std::size_t do_deprecated_write(std::size_t offset, const void* buf, std::size_t toWrite) { return write_from_start(buf, toWrite, offset); }
+
+    SOCI_NOT_COPYABLE(blob_backend)
+};
+
+// polymorphic session backend
+
+class session_backend
+{
+public:
+    session_backend() : failoverCallback_(NULL), session_(NULL) {}
+    virtual ~session_backend() {}
+
+    virtual bool is_connected() = 0;
+
+    virtual void begin() = 0;
+    virtual void commit() = 0;
+    virtual void rollback() = 0;
+
+    // At least one of these functions is usually not implemented for any given
+    // backend as RDBMS support either sequences or auto-generated values, so
+    // we don't declare them as pure virtuals to avoid having to define trivial
+    // versions of them in the derived classes. However every backend should
+    // define at least one of them to allow the code using auto-generated values
+    // to work.
+    virtual bool get_next_sequence_value(session&, std::string const&, long long&)
+    {
+        return false;
+    }
+    virtual bool get_last_insert_id(session&, std::string const&, long long&)
+    {
+        return false;
+    }
+
+    // There is a set of standard SQL metadata structures that can be
+    // queried in a portable way - backends that are standard compliant
+    // do not need to override the following methods, which are intended
+    // to return a proper query for basic metadata statements.
+
+    // Returns a parameterless query for the list of table names in the current schema.
+    virtual std::string get_table_names_query() const
+    {
+        return "select table_name as \"TABLE_NAME\""
+            " from information_schema.tables"
+            " where table_schema = 'public'";
+    }
+
+    // Returns a query with a single parameter (table name) for the list
+    // of columns and their properties.
+    virtual std::string get_column_descriptions_query() const
+    {
+        return "select column_name as \"COLUMN_NAME\","
+            " data_type as \"DATA_TYPE\","
+            " character_maximum_length as \"CHARACTER_MAXIMUM_LENGTH\","
+            " numeric_precision as \"NUMERIC_PRECISION\","
+            " numeric_scale as \"NUMERIC_SCALE\","
+            " is_nullable as \"IS_NULLABLE\""
+            " from information_schema.columns"
+            " where table_schema = 'public' and table_name = :t";
+    }
+
+    virtual std::string create_table(const std::string & tableName)
+    {
+        return "create table " + tableName + " (";
+    }
+    virtual std::string drop_table(const std::string & tableName)
+    {
+        return "drop table " + tableName;
+    }
+    virtual std::string truncate_table(const std::string & tableName)
+    {
+        return "truncate table " + tableName;
+    }
+
+    virtual std::string create_column_type(db_type dt,
+        int precision, int scale)
+    {
+        // PostgreSQL was selected as a baseline for the syntax:
+
+        std::string res;
+        switch (dt)
+        {
+        case db_string:
+            {
+                std::ostringstream oss;
+
+                if (precision == 0)
+                {
+                    oss << "text";
+                }
+                else
+                {
+                    oss << "varchar(" << precision << ")";
+                }
+
+                res += oss.str();
+            }
+            break;
+
+        case db_date:
+            res += "timestamp";
+            break;
+
+        case db_double:
+            {
+                std::ostringstream oss;
+                if (precision == 0)
+                {
+                    oss << "numeric";
+                }
+                else
+                {
+                    oss << "numeric(" << precision << ", " << scale << ")";
+                }
+
+                res += oss.str();
+            }
+            break;
+
+        case db_int16:
+        case db_uint16:
+            res += "smallint";
+            break;
+
+        case db_int32:
+        case db_uint32:
+            res += "integer";
+            break;
+
+        case db_int64:
+        case db_uint64:
+            res += "bigint";
+            break;
+
+        case db_blob:
+            res += "oid";
+            break;
+
+        case db_xml:
+            res += "xml";
+            break;
+
+        default:
+            throw soci_error("this db_type is not supported in create_column");
+        }
+
+        return res;
+    }
+
+    virtual std::string add_column(const std::string & tableName,
+                                   const std::string & columnName,
+                                   db_type dt,
+                                   int precision, int scale)
+    {
+        return "alter table " + tableName + " add column " + columnName +
+               " " + create_column_type(dt, precision, scale);
+    }
+    virtual std::string alter_column(const std::string & tableName,
+                                     const std::string & columnName,
+                                     db_type dt,
+                                     int precision, int scale)
+    {
+        return "alter table " + tableName + " alter column " +
+               columnName + " type " +
+               create_column_type(dt, precision, scale);
+    }
+    virtual std::string drop_column(const std::string & tableName,
+        const std::string & columnName)
+    {
+        return "alter table " + tableName +
+            " drop column " + columnName;
+    }
+    virtual std::string constraint_unique(const std::string & name,
+        const std::string & columnNames)
+    {
+        return "constraint " + name +
+            " unique (" + columnNames + ")";
+    }
+    virtual std::string constraint_primary_key(const std::string & name,
+        const std::string & columnNames)
+    {
+        return "constraint " + name +
+            " primary key (" + columnNames + ")";
+    }
+    virtual std::string constraint_foreign_key(const std::string & name,
+        const std::string & columnNames,
+        const std::string & refTableName,
+        const std::string & refColumnNames)
+    {
+        return "constraint " + name +
+            " foreign key (" + columnNames + ")" +
+            " references " + refTableName + " (" + refColumnNames + ")";
+    }
+    virtual std::string empty_blob()
+    {
+        return "lo_creat(-1)";
+    }
+    virtual std::string nvl()
+    {
+        return "coalesce";
+    }
+
+    virtual std::string get_dummy_from_table() const = 0;
+
+    void set_failover_callback(failover_callback & callback, session & sql)
+    {
+        failoverCallback_ = &callback;
+        session_ = &sql;
+    }
+
+    virtual std::string get_backend_name() const = 0;
+
+    virtual statement_backend* make_statement_backend() = 0;
+    virtual rowid_backend* make_rowid_backend() = 0;
+    virtual blob_backend* make_blob_backend() = 0;
+
+    // The functions below still work but are deprecated (but we don't give
+    // deprecation warnings for them because there is no real harm in using
+    // them).
+    //
+    // Use the overloads taking db_type instead in the new code.
+    std::string create_column_type(data_type dt, int precision, int scale)
+    {
+        return create_column_type(to_db_type(dt), precision, scale);
+    }
+
+    std::string add_column(const std::string & tableName,
+        const std::string & columnName, data_type dt,
+        int precision, int scale)
+    {
+        return add_column(tableName, columnName, to_db_type(dt), precision, scale);
+    }
+
+    std::string alter_column(const std::string & tableName,
+        const std::string & columnName, data_type dt,
+        int precision, int scale)
+    {
+        return alter_column(tableName, columnName, to_db_type(dt), precision, scale);
+    }
+
+
+    failover_callback * failoverCallback_;
+    session * session_;
+
+private:
+    SOCI_NOT_COPYABLE(session_backend)
+};
+
+} // namespace details
+
+// simple base class for the session back-end factory
+
+class connection_parameters;
+
+class SOCI_DECL backend_factory
+{
+public:
+    backend_factory() {}
+    virtual ~backend_factory() {}
+
+    virtual details::session_backend* make_session(
+        connection_parameters const& parameters) const = 0;
+};
+
+} // namespace soci
+
+#endif // SOCI_BACKEND_H_INCLUDED

+ 16 - 0
3rdparty/soci/include/soci/soci-config.h

@@ -0,0 +1,16 @@
+//
+// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCICONFIG_H_INCLUDED
+#define SOCICONFIG_H_INCLUDED
+
+//
+// SOCI has been build with support for:
+//
+//@CONFIGURED_VARIABLES@
+
+#endif // SOCICONFIG_H_INCLUDED

+ 197 - 0
3rdparty/soci/include/soci/soci-platform.h

@@ -0,0 +1,197 @@
+//
+// Copyright (C) 2006-2008 Mateusz Loskot
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_PLATFORM_H_INCLUDED
+#define SOCI_PLATFORM_H_INCLUDED
+
+//disable MSVC deprecated warnings
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include <stdarg.h>
+#include <string.h>
+#include <string>
+#include <cstring>
+#include <cstdlib>
+#include <ctime>
+#include <memory>
+
+#include "soci/soci-config.h" // for SOCI_HAVE_CXX11
+
+#if defined(_MSC_VER)
+#define LL_FMT_FLAGS "I64"
+#else
+#define LL_FMT_FLAGS "ll"
+#endif
+
+// Portability hacks for Microsoft Visual C++ compiler
+#ifdef _MSC_VER
+#include <stdlib.h>
+
+//Disables warnings about STL objects need to have dll-interface and/or
+//base class must have dll interface
+#pragma warning(disable:4251 4275)
+
+
+// Define if you have the vsnprintf variants.
+#if _MSC_VER < 1500
+# define vsnprintf _vsnprintf
+#endif
+
+// Define if you have the snprintf variants.
+#if _MSC_VER < 1900
+# define snprintf _snprintf
+#endif
+
+// Define if you have the strtoll and strtoull variants.
+#if _MSC_VER < 1300
+# error "Visual C++ versions prior 1300 don't support _strtoi64 and _strtoui64"
+#elif _MSC_VER >= 1300 && _MSC_VER < 1800
+namespace std {
+    inline long long strtoll(char const* str, char** str_end, int base)
+    {
+        return _strtoi64(str, str_end, base);
+    }
+
+    inline unsigned long long strtoull(char const* str, char** str_end, int base)
+    {
+        return _strtoui64(str, str_end, base);
+    }
+}
+#endif // _MSC_VER < 1800
+#endif // _MSC_VER
+
+#if defined(__CYGWIN__) || defined(__MINGW32__)
+#include <stdlib.h>
+namespace std {
+    using ::strtoll;
+    using ::strtoull;
+}
+#endif
+
+#ifdef _WIN32
+# ifndef _WIN32_WINNT
+#   define _WIN32_WINNT 0x0502 //_WIN32_WINNT_WS03, VS2015 support: https://msdn.microsoft.com/de-de/library/6sehtctf.aspx
+# endif
+
+# ifdef SOCI_DLL
+#  define SOCI_DECL_EXPORT __declspec(dllexport)
+#  define SOCI_DECL_IMPORT __declspec(dllimport)
+# endif
+
+#elif defined(SOCI_HAVE_VISIBILITY_SUPPORT)
+# define SOCI_DECL_EXPORT __attribute__ (( visibility("default") ))
+# define SOCI_DECL_IMPORT __attribute__ (( visibility("default") ))
+#endif
+
+#ifndef SOCI_DECL_EXPORT
+# define SOCI_DECL_EXPORT
+# define SOCI_DECL_IMPORT
+#endif
+
+// Define SOCI_DECL
+#ifdef SOCI_SOURCE
+# define SOCI_DECL SOCI_DECL_EXPORT
+#else
+# define SOCI_DECL SOCI_DECL_IMPORT
+#endif
+
+// C++11 features are always available in MSVS as it has no separate C++98
+// mode, we just need to check for the minimal compiler version supporting them
+// (see https://msdn.microsoft.com/en-us/library/hh567368.aspx).
+
+#ifdef _MSC_VER
+    #if _MSC_VER < 1900
+        #error This version of SOCI requires MSVS 2015 or later.
+    #endif
+    #if _MSVC_LANG >= 201703L
+        #define SOCI_HAVE_CXX17
+    #endif
+#else
+    #if __cplusplus < 201402L
+        #error This version of SOCI requires C++14.
+    #endif
+    #if __cplusplus >= 201703L
+        #define SOCI_HAVE_CXX17
+    #endif
+#endif
+
+// Define SOCI_ALLOW_DEPRECATED_BEGIN and SOCI_ALLOW_DEPRECATED_END
+// Ref.: https://www.fluentcpp.com/2019/08/30/how-to-disable-a-warning-in-cpp/
+#if defined(__GNUC__) || defined(__clang__)
+# define SOCI_ALLOW_DEPRECATED_BEGIN \
+    _Pragma("GCC diagnostic push") \
+    _Pragma("GCC diagnostic ignored \"-Wdeprecated\"") \
+    _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
+# define SOCI_ALLOW_DEPRECATED_END \
+    _Pragma("GCC diagnostic pop")
+#elif defined(_MSC_VER)
+# define SOCI_ALLOW_DEPRECATED_BEGIN \
+    __pragma(warning(push)) \
+    __pragma(warning(disable: 4973 )) \
+    __pragma(warning(disable: 4974 )) \
+    __pragma(warning(disable: 4995 )) \
+    __pragma(warning(disable: 4996 ))
+# define SOCI_ALLOW_DEPRECATED_END \
+    __pragma(warning(pop))
+# define SOCI_DONT_WARN(statement) statement
+#else
+# pragma message("WARNING: SOCI_ALLOW_DEPRECATED_* not available for this compilet")
+# define SOCI_ALLOW_DEPRECATED_BEGIN
+# define SOCI_ALLOW_DEPRECATED_END
+#endif
+
+#define SOCI_NOT_ASSIGNABLE(classname) \
+public: \
+    classname(const classname&) = default; \
+private: \
+    classname& operator=(const classname&) = delete;
+#define SOCI_NOT_COPYABLE(classname) \
+    classname(const classname&) = delete; \
+    classname& operator=(const classname&) = delete;
+
+#define SOCI_UNUSED(x) (void)x;
+
+// This macro can be used to avoid warnings from MSVC (and sometimes from gcc,
+// if initialization is indirect) about "uninitialized" variables that are
+// actually always initialized. Using this macro makes it clear that the
+// initialization is only necessary to avoid compiler warnings and also will
+// allow us to define it as doing nothing if we ever use a compiler warning
+// about initializing variables unnecessarily.
+#define SOCI_DUMMY_INIT(x) (x)
+
+// And this one can be used to return after calling a "[[noreturn]]" function.
+// Here the problem is that MSVC complains about unreachable code in this case
+// (but only in release builds, where optimizations are enabled), while other
+// compilers complain about missing return statement without it.
+#if defined(_MSC_VER) && defined(NDEBUG)
+    #define SOCI_DUMMY_RETURN(x)
+#else
+    #define SOCI_DUMMY_RETURN(x) return x
+#endif
+
+#define SOCI_OS_LINUX       0x0001
+#define SOCI_OS_FREE_BSD    0x0002
+#define SOCI_OS_APPLE       0x0003
+#define SOCI_OS_WINDOWS     0x0004
+
+#if defined(linux) || defined(__linux) || defined(__linux__)
+    #define SOCI_OS SOCI_OS_LINUX
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+    #define SOCI_OS SOCI_OS_FREE_BSD
+#elif defined(__APPLE__)
+    #define SOCI_OS SOCI_OS_APPLE
+#elif defined(_WIN32) || defined(_WIN64)
+    #define SOCI_OS SOCI_OS_WINDOWS
+#endif
+
+#if !defined(SOCI_OS)
+    #error "Unknown platform"
+#endif
+
+#endif // SOCI_PLATFORM_H_INCLUDED

+ 244 - 0
3rdparty/soci/include/soci/soci-simple.h

@@ -0,0 +1,244 @@
+//
+// Copyright (C) 2008 Maciej Sobczak
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_SIMPLE_H_INCLUDED
+#define SOCI_SIMPLE_H_INCLUDED
+
+#include "soci/soci-platform.h"
+
+#include <cstdint>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+// session
+
+typedef void * session_handle;
+SOCI_DECL session_handle soci_create_session(char const * connectionString);
+SOCI_DECL void soci_destroy_session(session_handle s);
+
+SOCI_DECL void soci_begin(session_handle s);
+SOCI_DECL void soci_commit(session_handle s);
+SOCI_DECL void soci_rollback(session_handle s);
+
+SOCI_DECL int soci_session_state(session_handle s);
+SOCI_DECL char const * soci_session_error_message(session_handle s);
+
+
+// blob
+
+typedef void *blob_handle;
+SOCI_DECL blob_handle soci_create_blob(session_handle s);
+SOCI_DECL void soci_destroy_blob(blob_handle b);
+
+SOCI_DECL int soci_blob_get_len(blob_handle b);
+[[deprecated("Use soci_blob_read_from_start instead")]]
+SOCI_DECL int soci_blob_read(blob_handle b, int offset, char *buf, int toRead);
+SOCI_DECL int soci_blob_read_from_start(blob_handle b, char *buf, int toRead, int offset = 0);
+[[deprecated("Use soci_blob_write_from_start instead")]]
+SOCI_DECL int soci_blob_write(blob_handle b, int offset, char const *buf, int toWrite);
+SOCI_DECL int soci_blob_write_from_start(blob_handle b, char const *buf, int toWrite, int offset = 0);
+SOCI_DECL int soci_blob_append(blob_handle b, char const *buf, int toWrite);
+SOCI_DECL int soci_blob_trim(blob_handle b, int newLen);
+
+SOCI_DECL int soci_blob_state(blob_handle b);
+SOCI_DECL char const * soci_blob_error_message(blob_handle b);
+
+
+// statement
+
+typedef void * statement_handle;
+SOCI_DECL statement_handle soci_create_statement(session_handle s);
+SOCI_DECL void soci_destroy_statement(statement_handle st);
+
+// positional bind of into elments (the functions return the position for convenience)
+SOCI_DECL int soci_into_string   (statement_handle st);
+SOCI_DECL int soci_into_int      (statement_handle st);
+SOCI_DECL int soci_into_long_long(statement_handle st);
+SOCI_DECL int soci_into_int8     (statement_handle st);
+SOCI_DECL int soci_into_uint8    (statement_handle st);
+SOCI_DECL int soci_into_int16    (statement_handle st);
+SOCI_DECL int soci_into_uint16   (statement_handle st);
+SOCI_DECL int soci_into_int32    (statement_handle st);
+SOCI_DECL int soci_into_uint32   (statement_handle st);
+SOCI_DECL int soci_into_int64    (statement_handle st);
+SOCI_DECL int soci_into_uint64   (statement_handle st);
+SOCI_DECL int soci_into_double   (statement_handle st);
+SOCI_DECL int soci_into_date     (statement_handle st);
+SOCI_DECL int soci_into_blob     (statement_handle st);
+
+// vector versions
+SOCI_DECL int soci_into_string_v   (statement_handle st);
+SOCI_DECL int soci_into_int_v      (statement_handle st);
+SOCI_DECL int soci_into_long_long_v(statement_handle st);
+SOCI_DECL int soci_into_int8_v     (statement_handle st);
+SOCI_DECL int soci_into_uint8_v    (statement_handle st);
+SOCI_DECL int soci_into_int16_v    (statement_handle st);
+SOCI_DECL int soci_into_uint16_v   (statement_handle st);
+SOCI_DECL int soci_into_int32_v    (statement_handle st);
+SOCI_DECL int soci_into_uint32_v   (statement_handle st);
+SOCI_DECL int soci_into_int64_v    (statement_handle st);
+SOCI_DECL int soci_into_uint64_v   (statement_handle st);
+SOCI_DECL int soci_into_double_v   (statement_handle st);
+SOCI_DECL int soci_into_date_v     (statement_handle st);
+
+// positional read of into elements
+SOCI_DECL int          soci_get_into_state    (statement_handle st, int position);
+SOCI_DECL char const * soci_get_into_string   (statement_handle st, int position);
+SOCI_DECL int          soci_get_into_int      (statement_handle st, int position);
+SOCI_DECL long long    soci_get_into_long_long(statement_handle st, int position);
+SOCI_DECL int8_t       soci_get_into_int8     (statement_handle st, int position);
+SOCI_DECL uint8_t      soci_get_into_uint8    (statement_handle st, int position);
+SOCI_DECL int16_t      soci_get_into_int16    (statement_handle st, int position);
+SOCI_DECL uint16_t     soci_get_into_uint16   (statement_handle st, int position);
+SOCI_DECL int32_t      soci_get_into_int32    (statement_handle st, int position);
+SOCI_DECL uint32_t     soci_get_into_uint32   (statement_handle st, int position);
+SOCI_DECL int64_t      soci_get_into_int64    (statement_handle st, int position);
+SOCI_DECL uint64_t     soci_get_into_uint64   (statement_handle st, int position);
+SOCI_DECL double       soci_get_into_double   (statement_handle st, int position);
+SOCI_DECL char const * soci_get_into_date     (statement_handle st, int position);
+SOCI_DECL blob_handle  soci_get_into_blob     (statement_handle st, int position);
+
+// positional (re)size of vectors
+SOCI_DECL int  soci_into_get_size_v(statement_handle st);
+SOCI_DECL void soci_into_resize_v  (statement_handle st, int new_size);
+
+// positional read of vectors
+SOCI_DECL int          soci_get_into_state_v    (statement_handle st, int position, int index);
+SOCI_DECL char const * soci_get_into_string_v   (statement_handle st, int position, int index);
+SOCI_DECL int          soci_get_into_int_v      (statement_handle st, int position, int index);
+SOCI_DECL long long    soci_get_into_long_long_v(statement_handle st, int position, int index);
+SOCI_DECL int8_t       soci_get_into_int8_v     (statement_handle st, int position, int index);
+SOCI_DECL uint8_t      soci_get_into_uint8_v    (statement_handle st, int position, int index);
+SOCI_DECL int16_t      soci_get_into_int16_v    (statement_handle st, int position, int index);
+SOCI_DECL uint16_t     soci_get_into_uint16_v   (statement_handle st, int position, int index);
+SOCI_DECL int32_t      soci_get_into_int32_v    (statement_handle st, int position, int index);
+SOCI_DECL uint32_t     soci_get_into_uint32_v   (statement_handle st, int position, int index);
+SOCI_DECL int64_t      soci_get_into_int64_v    (statement_handle st, int position, int index);
+SOCI_DECL uint64_t     soci_get_into_uint64_v   (statement_handle st, int position, int index);
+SOCI_DECL double       soci_get_into_double_v   (statement_handle st, int position, int index);
+SOCI_DECL char const * soci_get_into_date_v     (statement_handle st, int position, int index);
+
+
+// named bind of use elements
+SOCI_DECL void soci_use_string   (statement_handle st, char const * name);
+SOCI_DECL void soci_use_int      (statement_handle st, char const * name);
+SOCI_DECL void soci_use_long_long(statement_handle st, char const * name);
+SOCI_DECL void soci_use_int8     (statement_handle st, char const * name);
+SOCI_DECL void soci_use_uint8    (statement_handle st, char const * name);
+SOCI_DECL void soci_use_int16    (statement_handle st, char const * name);
+SOCI_DECL void soci_use_uint16   (statement_handle st, char const * name);
+SOCI_DECL void soci_use_int32    (statement_handle st, char const * name);
+SOCI_DECL void soci_use_uint32   (statement_handle st, char const * name);
+SOCI_DECL void soci_use_int64    (statement_handle st, char const * name);
+SOCI_DECL void soci_use_uint64   (statement_handle st, char const * name);
+SOCI_DECL void soci_use_double   (statement_handle st, char const * name);
+SOCI_DECL void soci_use_date     (statement_handle st, char const * name);
+SOCI_DECL void soci_use_blob     (statement_handle st, char const * name);
+
+// vector versions
+SOCI_DECL void soci_use_string_v   (statement_handle st, char const * name);
+SOCI_DECL void soci_use_int_v      (statement_handle st, char const * name);
+SOCI_DECL void soci_use_long_long_v(statement_handle st, char const * name);
+SOCI_DECL void soci_use_int8_v     (statement_handle st, char const * name);
+SOCI_DECL void soci_use_uint8_v    (statement_handle st, char const * name);
+SOCI_DECL void soci_use_int16_v    (statement_handle st, char const * name);
+SOCI_DECL void soci_use_uint16_v   (statement_handle st, char const * name);
+SOCI_DECL void soci_use_int32_v    (statement_handle st, char const * name);
+SOCI_DECL void soci_use_uint32_v   (statement_handle st, char const * name);
+SOCI_DECL void soci_use_int64_v    (statement_handle st, char const * name);
+SOCI_DECL void soci_use_uint64_v   (statement_handle st, char const * name);
+SOCI_DECL void soci_use_double_v   (statement_handle st, char const * name);
+SOCI_DECL void soci_use_date_v     (statement_handle st, char const * name);
+
+// named write of use elements
+SOCI_DECL void soci_set_use_state    (statement_handle st, char const * name, int state);
+SOCI_DECL void soci_set_use_string   (statement_handle st, char const * name, char const * val);
+SOCI_DECL void soci_set_use_int      (statement_handle st, char const * name, int val);
+SOCI_DECL void soci_set_use_long_long(statement_handle st, char const * name, long long val);
+SOCI_DECL void soci_set_use_int8     (statement_handle st, char const * name, int8_t val);
+SOCI_DECL void soci_set_use_uint8    (statement_handle st, char const * name, uint8_t val);
+SOCI_DECL void soci_set_use_int18    (statement_handle st, char const * name, int16_t val);
+SOCI_DECL void soci_set_use_uint18   (statement_handle st, char const * name, uint16_t val);
+SOCI_DECL void soci_set_use_int32    (statement_handle st, char const * name, int32_t val);
+SOCI_DECL void soci_set_use_uint32   (statement_handle st, char const * name, uint32_t val);
+SOCI_DECL void soci_set_use_int64    (statement_handle st, char const * name, int64_t val);
+SOCI_DECL void soci_set_use_uint64   (statement_handle st, char const * name, uint64_t val);
+SOCI_DECL void soci_set_use_double   (statement_handle st, char const * name, double val);
+SOCI_DECL void soci_set_use_date     (statement_handle st, char const * name, char const * val);
+SOCI_DECL void soci_set_use_blob     (statement_handle st, char const * name, blob_handle blob);
+
+// positional (re)size of vectors
+SOCI_DECL int  soci_use_get_size_v(statement_handle st);
+SOCI_DECL void soci_use_resize_v  (statement_handle st, int new_size);
+
+// named write of use vectors
+SOCI_DECL void soci_set_use_state_v(statement_handle st,
+    char const * name, int index, int state);
+SOCI_DECL void soci_set_use_string_v(statement_handle st,
+    char const * name, int index, char const * val);
+SOCI_DECL void soci_set_use_int_v(statement_handle st,
+    char const * name, int index, int val);
+SOCI_DECL void soci_set_use_long_long_v(statement_handle st,
+    char const * name, int index, long long val);
+SOCI_DECL void soci_set_use_int8_v(statement_handle st,
+    char const * name, int index, int8_t val);
+SOCI_DECL void soci_set_use_uint8_v(statement_handle st,
+    char const * name, int index, uint8_t val);
+SOCI_DECL void soci_set_use_int16_v(statement_handle st,
+    char const * name, int index, int16_t val);
+SOCI_DECL void soci_set_use_uint16_v(statement_handle st,
+    char const * name, int index, uint16_t val);
+SOCI_DECL void soci_set_use_int32_v(statement_handle st,
+    char const * name, int index, int32_t val);
+SOCI_DECL void soci_set_use_uint32_v(statement_handle st,
+    char const * name, int index, uint32_t val);
+SOCI_DECL void soci_set_use_int64_v(statement_handle st,
+    char const * name, int index, int64_t val);
+SOCI_DECL void soci_set_use_uint64_v(statement_handle st,
+    char const * name, int index, uint64_t val);
+SOCI_DECL void soci_set_use_double_v(statement_handle st,
+    char const * name, int index, double val);
+SOCI_DECL void soci_set_use_date_v(statement_handle st,
+    char const * name, int index, char const * val);
+
+
+// named read of use elements (for modifiable use values)
+SOCI_DECL int          soci_get_use_state    (statement_handle st, char const * name);
+SOCI_DECL char const * soci_get_use_string   (statement_handle st, char const * name);
+SOCI_DECL int          soci_get_use_int      (statement_handle st, char const * name);
+SOCI_DECL long long    soci_get_use_long_long(statement_handle st, char const * name);
+SOCI_DECL int8_t       soci_get_use_int8     (statement_handle st, char const * name);
+SOCI_DECL uint8_t      soci_get_use_uint8    (statement_handle st, char const * name);
+SOCI_DECL int16_t      soci_get_use_int16    (statement_handle st, char const * name);
+SOCI_DECL uint16_t     soci_get_use_uint16   (statement_handle st, char const * name);
+SOCI_DECL int32_t      soci_get_use_int32    (statement_handle st, char const * name);
+SOCI_DECL uint32_t     soci_get_use_uint32   (statement_handle st, char const * name);
+SOCI_DECL int64_t      soci_get_use_int64    (statement_handle st, char const * name);
+SOCI_DECL uint64_t     soci_get_use_uint64   (statement_handle st, char const * name);
+SOCI_DECL double       soci_get_use_double   (statement_handle st, char const * name);
+SOCI_DECL char const * soci_get_use_date     (statement_handle st, char const * name);
+SOCI_DECL blob_handle  soci_get_use_blob     (statement_handle st, char const * name);
+
+
+// statement preparation and execution
+SOCI_DECL void      soci_prepare(statement_handle st, char const * query);
+SOCI_DECL int       soci_execute(statement_handle st, int withDataExchange);
+SOCI_DECL long long soci_get_affected_rows(statement_handle st);
+SOCI_DECL int       soci_fetch(statement_handle st);
+SOCI_DECL int       soci_got_data(statement_handle st);
+
+SOCI_DECL int soci_statement_state(statement_handle s);
+SOCI_DECL char const * soci_statement_error_message(statement_handle s);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif // __cplusplus
+
+#endif // SOCI_SIMPLE_H_INCLUDED

+ 15 - 0
3rdparty/soci/include/soci/soci-types.h

@@ -0,0 +1,15 @@
+#ifndef SOCI_TYPES_H_INCLUDED
+#define SOCI_TYPES_H_INCLUDED
+
+#include "soci/soci-platform.h"
+
+#if defined(__GNUC__) || defined(__clang__)
+    #if defined(__LP64__)
+        #define SOCI_LONG_IS_64_BIT 1
+        #if SOCI_OS == SOCI_OS_LINUX || SOCI_OS == SOCI_OS_FREE_BSD
+            #define SOCI_INT64_IS_LONG 1
+        #endif
+    #endif
+#endif
+
+#endif // SOCI_TYPES_H_INCLUDED

+ 63 - 0
3rdparty/soci/include/soci/soci.h

@@ -0,0 +1,63 @@
+//
+// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_H_INCLUDED
+#define SOCI_H_INCLUDED
+
+// namespace soci
+#include "soci/soci-platform.h"
+#include "soci/backend-loader.h"
+#include "soci/blob.h"
+#include "soci/blob-exchange.h"
+#include "soci/column-info.h"
+#include "soci/connection-pool.h"
+#include "soci/error.h"
+#include "soci/exchange-traits.h"
+#include "soci/fixed-size-ints.h"
+#include "soci/into.h"
+#include "soci/into-type.h"
+#include "soci/once-temp-type.h"
+#include "soci/prepare-temp-type.h"
+#include "soci/procedure.h"
+#include "soci/ref-counted-prepare-info.h"
+#include "soci/ref-counted-statement.h"
+#include "soci/row.h"
+#include "soci/row-exchange.h"
+#include "soci/rowid.h"
+#include "soci/rowid-exchange.h"
+#include "soci/rowset.h"
+#include "soci/session.h"
+#include "soci/soci-backend.h"
+#include "soci/statement.h"
+#include "soci/transaction.h"
+#include "soci/type-conversion.h"
+#include "soci/type-conversion-traits.h"
+#include "soci/type-holder.h"
+#include "soci/type-ptr.h"
+#include "soci/type-wrappers.h"
+#include "soci/use.h"
+#include "soci/use-type.h"
+#include "soci/values.h"
+#include "soci/values-exchange.h"
+
+// namespace boost
+#ifdef SOCI_USE_BOOST
+#include <boost/version.hpp>
+#if defined(BOOST_VERSION) && BOOST_VERSION >= 103500
+#include "soci/boost-fusion.h"
+#endif // BOOST_VERSION
+#include "soci/boost-optional.h"
+#include "soci/boost-tuple.h"
+#include "soci/boost-gregorian-date.h"
+#endif // SOCI_USE_BOOST
+
+// C++17
+#ifdef SOCI_HAVE_CXX17
+#include "soci/std-optional.h"
+#endif // SOCI_HAVE_CXX17
+
+#endif // SOCI_H_INCLUDED

+ 384 - 0
3rdparty/soci/include/soci/sqlite3/soci-sqlite3.h

@@ -0,0 +1,384 @@
+//
+// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_SQLITE3_H_INCLUDED
+#define SOCI_SQLITE3_H_INCLUDED
+
+#include <soci/soci-platform.h>
+
+#ifdef SOCI_SQLITE3_SOURCE
+# define SOCI_SQLITE3_DECL SOCI_DECL_EXPORT
+#else
+# define SOCI_SQLITE3_DECL SOCI_DECL_IMPORT
+#endif
+
+#include <cstdarg>
+#include <cstdint>
+#include <vector>
+#include <soci/soci-backend.h>
+#include <private/soci-trivial-blob-backend.h>
+
+// Disable flood of nonsense warnings generated for SQLite
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4510 4512 4610)
+#endif
+
+namespace sqlite_api
+{
+
+#if SQLITE_VERSION_NUMBER < 3003010
+// The sqlite3_destructor_type typedef introduced in 3.3.10
+// http://www.sqlite.org/cvstrac/tktview?tn=2191
+typedef void (*sqlite3_destructor_type)(void*);
+#endif
+
+#include <sqlite3.h>
+
+} // namespace sqlite_api
+
+#undef SQLITE_STATIC
+#define SQLITE_STATIC ((sqlite_api::sqlite3_destructor_type)0)
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+namespace soci
+{
+
+class SOCI_SQLITE3_DECL sqlite3_soci_error : public soci_error
+{
+public:
+    sqlite3_soci_error(std::string const & msg, int result);
+
+    int result() const;
+
+private:
+    int result_;
+};
+
+struct sqlite3_statement_backend;
+struct sqlite3_standard_into_type_backend : details::standard_into_type_backend
+{
+    sqlite3_standard_into_type_backend(sqlite3_statement_backend &st)
+        : statement_(st), data_(0), type_(), position_(0)
+    {
+    }
+
+    void define_by_pos(int &position,
+                             void *data, details::exchange_type type) override;
+
+    void pre_fetch() override;
+    void post_fetch(bool gotData, bool calledFromFetch,
+                           indicator *ind) override;
+
+    void clean_up() override;
+
+    sqlite3_statement_backend &statement_;
+
+    void *data_;
+    details::exchange_type type_;
+    int position_;
+};
+
+struct sqlite3_vector_into_type_backend : details::vector_into_type_backend
+{
+    sqlite3_vector_into_type_backend(sqlite3_statement_backend &st)
+        : statement_(st), data_(0), type_(), position_(0)
+    {
+    }
+
+    void define_by_pos(int& position, void* data, details::exchange_type type) override;
+
+    void pre_fetch() override;
+    void post_fetch(bool gotData, indicator* ind) override;
+
+    void resize(std::size_t sz) override;
+    std::size_t size() override;
+
+    void clean_up() override;
+
+    sqlite3_statement_backend& statement_;
+
+    void *data_;
+    details::exchange_type type_;
+    int position_;
+};
+
+struct sqlite3_standard_use_type_backend : details::standard_use_type_backend
+{
+    sqlite3_standard_use_type_backend(sqlite3_statement_backend &st);
+
+    void bind_by_pos(int &position,
+        void *data, details::exchange_type type, bool readOnly) override;
+    void bind_by_name(std::string const &name,
+        void *data, details::exchange_type type, bool readOnly) override;
+
+    void pre_use(indicator const *ind) override;
+    void post_use(bool gotData, indicator *ind) override;
+
+    void clean_up() override;
+
+    sqlite3_statement_backend &statement_;
+
+    void *data_;                    // pointer to used data: soci::use(myvariable) --> data_ = &myvariable
+    details::exchange_type type_;   // type of data_
+    int position_;                  // binding position
+    std::string name_;              // binding name
+};
+
+struct sqlite3_vector_use_type_backend : details::vector_use_type_backend
+{
+    sqlite3_vector_use_type_backend(sqlite3_statement_backend &st)
+        : statement_(st), data_(0), type_(), position_(0)
+    {
+    }
+
+    void bind_by_pos(int &position,
+                           void *data, details::exchange_type type) override;
+    void bind_by_name(std::string const &name,
+                            void *data, details::exchange_type type) override;
+
+    void pre_use(indicator const *ind) override;
+
+    std::size_t size() override;
+
+    void clean_up() override;
+
+    sqlite3_statement_backend &statement_;
+
+    void *data_;
+    details::exchange_type type_;
+    int position_;
+    std::string name_;
+};
+
+struct sqlite3_column_buffer
+{
+    std::size_t size_;
+    union
+    {
+        const char *constData_;
+        char *data_;
+    };
+};
+
+struct sqlite3_column
+{
+    bool isNull_;
+    // DEPRECATED. USE dataType_ INSTEAD.
+    data_type type_;
+    db_type dataType_;
+
+    union
+    {
+        sqlite3_column_buffer buffer_;
+        int8_t int8_;
+        uint8_t uint8_;
+        int16_t int16_;
+        uint16_t uint16_;
+        int32_t int32_;
+        uint32_t uint32_;
+        sqlite_api::sqlite3_int64 int64_;
+        sqlite_api::sqlite3_uint64 uint64_;
+        double double_;
+    };
+};
+
+typedef std::vector<sqlite3_column> sqlite3_row;
+typedef std::vector<sqlite3_row> sqlite3_recordset;
+
+
+struct sqlite3_column_info
+{
+    // DEPRECATED. USE dataType_ INSTEAD.
+    data_type type_;
+    db_type dataType_;
+    std::string name_;
+};
+typedef std::vector<sqlite3_column_info> sqlite3_column_info_list;
+
+struct sqlite3_session_backend;
+struct sqlite3_statement_backend : details::statement_backend
+{
+    sqlite3_statement_backend(sqlite3_session_backend &session);
+
+    void alloc() override;
+    void clean_up() override;
+    void prepare(std::string const &query,
+        details::statement_type eType) override;
+    void reset_if_needed();
+    void reset();
+
+    exec_fetch_result execute(int number) override;
+    exec_fetch_result fetch(int number) override;
+
+    long long get_affected_rows() override;
+    int get_number_of_rows() override;
+    std::string get_parameter_name(int index) const override;
+
+    std::string rewrite_for_procedure_call(std::string const &query) override;
+
+    int prepare_for_describe() override;
+    void describe_column(int colNum,
+                                db_type &dbtype,
+                                std::string &columnName) override;
+
+    sqlite3_standard_into_type_backend * make_into_type_backend() override;
+    sqlite3_standard_use_type_backend * make_use_type_backend() override;
+    sqlite3_vector_into_type_backend * make_vector_into_type_backend() override;
+    sqlite3_vector_use_type_backend * make_vector_use_type_backend() override;
+
+    sqlite3_session_backend &session_;
+    sqlite_api::sqlite3_stmt *stmt_;
+    sqlite3_recordset dataCache_;
+    sqlite3_recordset useData_;
+    bool databaseReady_;
+    bool boundByName_;
+    bool boundByPos_;
+    sqlite3_column_info_list columns_;
+
+
+    bool hasVectorIntoElements_;
+    long long rowsAffectedBulk_; // number of rows affected by the last bulk operation
+
+private:
+    exec_fetch_result load_rowset(int totalRows);
+    exec_fetch_result load_one();
+    exec_fetch_result bind_and_execute(int number);
+};
+
+struct sqlite3_rowid_backend : details::rowid_backend
+{
+    sqlite3_rowid_backend(sqlite3_session_backend &session);
+
+    ~sqlite3_rowid_backend() override;
+
+    unsigned long value_;
+};
+
+struct sqlite3_blob_backend : details::trivial_blob_backend
+{
+    sqlite3_blob_backend(sqlite3_session_backend &session);
+
+    ~sqlite3_blob_backend() override;
+
+    void ensure_buffer_initialized();
+};
+
+struct sqlite3_session_backend : details::session_backend
+{
+    sqlite3_session_backend(connection_parameters const & parameters);
+
+    ~sqlite3_session_backend() override;
+
+    bool is_connected() override { return true; }
+
+    void begin() override;
+    void commit() override;
+    void rollback() override;
+
+    bool get_last_insert_id(session&, std::string const&, long long&) override;
+
+    std::string empty_blob() override
+    {
+        return "x\'\'";
+    }
+
+    std::string get_dummy_from_table() const override { return std::string(); }
+
+    std::string get_backend_name() const override { return "sqlite3"; }
+
+    void clean_up();
+
+    sqlite3_statement_backend * make_statement_backend() override;
+    sqlite3_rowid_backend * make_rowid_backend() override;
+    sqlite3_blob_backend * make_blob_backend() override;
+    std::string get_table_names_query() const override
+    {
+        return "select name as \"TABLE_NAME\""
+                " from sqlite_master where type = 'table'";
+    }
+    std::string get_column_descriptions_query() const override
+    {
+        return "select name as 'COLUMN_NAME',"
+            " 0 as 'CHARACTER_MAXIMUM_LENGTH',"
+            " 0 as 'NUMERIC_PRECISION',"
+            " case when type like '%real%' or type like '%float%' or type like '%double%' then 255 else 0 end as 'NUMERIC_SCALE',"
+            " case"
+                " when type like 'text'   or type like 'clob'     or type like '%char%'    then 'text'"
+                " when type like '%int%'  or type like '%number%' or type like '%numeric%' then 'integer'"
+                " when type like '%real%' or type like '%float%'  or type like '%double%'  then 'number'"
+                " else type"
+            " end as 'DATA_TYPE',"
+        " case when \"notnull\" = 0 then 'YES' else 'NO' end as 'IS_NULLABLE'"
+        " from (select name, lower(type) as type, \"notnull\" from pragma_table_info(:t))";
+    }
+    std::string create_column_type(db_type dt,
+                                   int , int ) override
+    {
+        switch (dt)
+        {
+            case db_xml:
+            case db_string:
+                return "text";
+            case db_double:
+                return "real";
+            case db_date:
+                return "integer";
+            case db_int8:
+                return "tinyint";
+            case db_uint8:
+                return "unsignedtinyint";
+            case db_int16:
+                return "smallint";
+            case db_uint16:
+                return "unsignedsmallint";
+            case db_int32:
+                return "integer";
+            case db_uint32:
+                return "unsignedint";
+            case db_int64:
+                return "bigint";
+            case db_uint64:
+                return "unsignedbigint";
+            case db_blob:
+                return "blob";
+            default:
+                throw soci_error("this db_type is not supported in create_column");
+        }
+    }
+
+    sqlite_api::sqlite3 *conn_;
+
+    // This flag is set to true if the internal sqlite_sequence table exists in
+    // the database.
+    bool sequence_table_exists_;
+};
+
+struct sqlite3_backend_factory : backend_factory
+{
+    sqlite3_backend_factory() {}
+    sqlite3_session_backend * make_session(
+        connection_parameters const & parameters) const override;
+};
+
+extern SOCI_SQLITE3_DECL sqlite3_backend_factory const sqlite3;
+
+extern "C"
+{
+
+// for dynamic backend loading
+SOCI_SQLITE3_DECL backend_factory const * factory_sqlite3();
+SOCI_SQLITE3_DECL void register_factory_sqlite3();
+
+} // extern "C"
+
+} // namespace soci
+
+#endif // SOCI_SQLITE3_H_INCLUDED

+ 329 - 0
3rdparty/soci/include/soci/statement.h

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

+ 55 - 0
3rdparty/soci/include/soci/std-optional.h

@@ -0,0 +1,55 @@
+//
+// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_STD_OPTIONAL_H_INCLUDED
+#define SOCI_STD_OPTIONAL_H_INCLUDED
+
+#include "soci/type-conversion-traits.h"
+
+#include <optional>
+
+namespace soci
+{
+
+// simple fall-back for std::optional
+template <typename T>
+struct type_conversion<std::optional<T> >
+{
+    typedef typename type_conversion<T>::base_type base_type;
+
+    static void from_base(base_type const & in, indicator ind,
+        std::optional<T> & out)
+    {
+        if (ind == i_null)
+        {
+            out.reset();
+        }
+        else
+        {
+            T tmp = T();
+            type_conversion<T>::from_base(in, ind, tmp);
+            out = tmp;
+        }
+    }
+
+    static void to_base(std::optional<T> const & in,
+        base_type & out, indicator & ind)
+    {
+        if (in)
+        {
+            type_conversion<T>::to_base(*in, out, ind);
+        }
+        else
+        {
+            ind = i_null;
+        }
+    }
+};
+
+} // namespace soci
+
+#endif // SOCI_STD_OPTIONAL_H_INCLUDED

+ 36 - 0
3rdparty/soci/include/soci/transaction.h

@@ -0,0 +1,36 @@
+//
+// Copyright (C) 2004-2008 Maciej Sobczak
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_TRANSACTION_H_INCLUDED
+#define SOCI_TRANSACTION_H_INCLUDED
+
+#include "soci/soci-platform.h"
+#include "soci/session.h"
+
+namespace soci
+{
+
+class SOCI_DECL transaction
+{
+public:
+    explicit transaction(session& sql);
+
+    ~transaction();
+
+    void commit();
+    void rollback();
+
+private:
+    bool handled_;
+    session& sql_;
+
+    SOCI_NOT_COPYABLE(transaction)
+};
+
+} // namespace soci
+
+#endif // SOCI_TRANSACTION_H_INCLUDED

+ 149 - 0
3rdparty/soci/include/soci/type-conversion-traits.h

@@ -0,0 +1,149 @@
+//
+// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_TYPE_CONVERSION_TRAITS_H_INCLUDED
+#define SOCI_TYPE_CONVERSION_TRAITS_H_INCLUDED
+
+#include "soci/soci-backend.h"
+#include "soci/is-detected.h"
+
+#include <type_traits>
+
+namespace soci
+{
+
+// default traits class type_conversion, acts as pass through for row::get() or row::move_as()
+// when no actual conversion is needed.
+template <typename T, typename Enable = void>
+struct type_conversion
+{
+    typedef T base_type;
+
+    struct from_base_check : std::integral_constant<bool, std::is_constructible<T, const base_type>::value> {};
+
+    static void from_base(base_type const& in, indicator ind, T & out)
+    {
+        static_assert(from_base_check::value,
+                "from_base can only be used if the target type can be constructed from an lvalue base reference");
+        assert_non_null(ind);
+        out = in;
+    }
+
+    struct move_from_base_check :
+        std::integral_constant<bool,
+            !std::is_const<base_type>::value
+            && std::is_constructible<T, typename std::add_rvalue_reference<base_type>::type>::value
+        > {};
+
+
+    static void move_from_base(base_type & in, indicator ind, T & out)
+    {
+        static_assert(move_from_base_check::value,
+                "move_to_base can only be used if the target type can be constructed from an rvalue base reference");
+        assert_non_null(ind);
+        out = std::move(in);
+    }
+
+    static void to_base(T const & in, base_type & out, indicator & ind)
+    {
+        out = in;
+        ind = i_ok;
+    }
+
+    static void move_to_base(T & in, base_type & out, indicator & ind)
+    {
+        out = std::move(in);
+        ind = i_ok;
+    }
+
+private:
+    static void assert_non_null(indicator ind)
+    {
+        if (ind == i_null)
+        {
+            throw soci_error("Null value not allowed for this type");
+        }
+    }
+};
+
+namespace details
+{
+
+#if !defined(_MSC_VER) || (_MSC_VER >= 1910)
+    // MSVC 2015 and earlier don't support SFINAE on return types
+    #define SOCI_HAS_RET_TYPE_SFINAE
+#endif
+
+template<typename T>
+using from_base_check_t = decltype(T::from_base_check::value);
+template<typename T>
+using move_from_base_check_t = decltype(T::move_from_base_check::value);
+
+template<typename T>
+using supports_from_base_check = is_detected<from_base_check_t, T>;
+template<typename T>
+using supports_move_from_base_check = is_detected<move_from_base_check_t, T>;
+
+#ifdef SOCI_HAS_RET_TYPE_SFINAE
+
+template<typename Trait>
+constexpr auto can_use_from_base()
+    -> typename std::enable_if<supports_from_base_check<Trait>::value, bool>::type
+{
+    return Trait::from_base_check::value;
+}
+
+template<typename Trait>
+constexpr auto can_use_from_base()
+    -> typename std::enable_if<!supports_from_base_check<Trait>::value, bool>::type
+{
+    return true;
+}
+
+template<typename Trait>
+constexpr auto can_use_move_from_base()
+    -> typename std::enable_if<supports_move_from_base_check<Trait>::value, bool>::type
+{
+    return Trait::from_base_check::value;
+}
+
+template<typename Trait>
+constexpr auto can_use_move_from_base()
+    -> typename std::enable_if<!supports_move_from_base_check<Trait>::value, bool>::type
+{
+    // Default to assuming that the special move_from_base function is not implemented
+    // TODO: Find clever template magic to add a metaprogramming check for a suitable
+    // move_from_base implementation
+    return false;
+}
+
+#undef SOCI_HAS_RET_TYPE_SFINAE
+
+#else
+
+// Always return true - if it doesn't work the user will get a cryptic compiler error but at least
+// it will compile properly for cases in which things do indeed work
+
+template<typename Trait>
+constexpr auto can_use_from_base()
+{
+    return true;
+}
+
+template<typename Trait>
+constexpr auto can_use_move_from_base()
+{
+    return true;
+}
+
+#endif
+
+}
+
+} // namespace soci
+
+#endif // SOCI_TYPE_CONVERSION_TRAITS_H_INCLUDED

+ 509 - 0
3rdparty/soci/include/soci/type-conversion.h

@@ -0,0 +1,509 @@
+//
+// Copyright (C) 2004-2016 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_TYPE_CONVERSION_H_INCLUDED
+#define SOCI_TYPE_CONVERSION_H_INCLUDED
+
+#include "soci/type-conversion-traits.h"
+#include "soci/into-type.h"
+#include "soci/use-type.h"
+// std
+#include <cstddef>
+#include <string>
+#include <vector>
+
+namespace soci
+{
+
+namespace details
+{
+
+// this class is used to ensure correct order of construction
+// of into_type and use_type elements that use type_conversion
+
+template <typename T>
+struct base_value_holder
+{
+    base_value_holder()
+      : ownInd_(i_ok)
+    {}
+
+    typename type_conversion<T>::base_type val_;
+    indicator ownInd_;
+};
+
+// Automatically create into_type from a type_conversion
+
+template <typename T>
+class conversion_into_type
+    : private base_value_holder<T>,
+      public into_type<typename type_conversion<T>::base_type>
+{
+public:
+    typedef typename type_conversion<T>::base_type base_type;
+
+    conversion_into_type(T & value)
+        : into_type<base_type>(base_value_holder<T>::val_, base_value_holder<T>::ownInd_)
+        , value_(value)
+        , ind_(base_value_holder<T>::ownInd_)
+    {
+    }
+
+    conversion_into_type(T & value, indicator & ind)
+        : into_type<base_type>(base_value_holder<T>::val_, ind)
+        , value_(value)
+        , ind_(ind)
+    {
+    }
+
+
+private:
+    void convert_from_base() override
+    {
+        type_conversion<T>::from_base(
+            base_value_holder<T>::val_, ind_, value_);
+    }
+
+    T & value_;
+
+    // ind_ refers to either ownInd_, or the one provided by the user
+    // in any case, ind_ refers to some valid indicator
+    // and can be used by conversion routines
+    indicator & ind_;
+
+    SOCI_NOT_COPYABLE(conversion_into_type)
+};
+
+// Automatically create use_type from a type_conversion
+
+template <typename T>
+class conversion_use_type
+    : private base_value_holder<T>,
+      public use_type<typename type_conversion<T>::base_type>
+{
+public:
+    typedef typename type_conversion<T>::base_type base_type;
+
+    conversion_use_type(T & value, std::string const & name = std::string())
+        : use_type<base_type>(base_value_holder<T>::val_, base_value_holder<T>::ownInd_, name)
+        , value_(value)
+        , ind_(base_value_holder<T>::ownInd_)
+        , readOnly_(false)
+    {
+        // TODO: likely to be removed (SHA: c166625a28f7c907318134f625ff5acea7d9a1f8)
+        //convert_to_base();
+    }
+
+    conversion_use_type(T const & value, std::string const & name = std::string())
+        : use_type<base_type>(base_value_holder<T>::val_, base_value_holder<T>::ownInd_, name)
+        , value_(const_cast<T &>(value))
+        , ind_(base_value_holder<T>::ownInd_)
+        , readOnly_(true)
+    {
+        // TODO: likely to be removed (SHA: c166625a28f7c907318134f625ff5acea7d9a1f8)
+        //convert_to_base();
+    }
+
+    conversion_use_type(T & value, indicator & ind,
+            std::string const & name = std::string())
+        : use_type<base_type>(base_value_holder<T>::val_, ind, name)
+        , value_(value)
+        , ind_(ind)
+        , readOnly_(false)
+    {
+        // TODO: likely to be removed (SHA: c166625a28f7c907318134f625ff5acea7d9a1f8)
+        //convert_to_base();
+    }
+
+    conversion_use_type(T const & value, indicator & ind,
+            std::string const & name = std::string())
+        : use_type<base_type>(base_value_holder<T>::val_, ind, name)
+        , value_(const_cast<T &>(value))
+        , ind_(ind)
+        , readOnly_(true)
+    {
+        // TODO: likely to be removed (SHA: c166625a28f7c907318134f625ff5acea7d9a1f8)
+        //convert_to_base();
+    }
+
+    void convert_from_base() override
+    {
+        // NOTE:
+        // readOnly_ flag indicates that use_type object has been generated
+        // based on non-const object passed by user as input argument.
+        // For const objects, this is effectively no-op conversion.
+        // See standard_use_type::post_use() for more details.
+
+        if (readOnly_ == false)
+        {
+            type_conversion<T>::from_base(
+                base_value_holder<T>::val_, ind_, value_);
+        }
+    }
+
+    void convert_to_base() override
+    {
+        if (ind_ == i_null)
+        {
+            // A null indicator was explicitly passed to use(val, ind).
+            // Therefore, NULL should be put into the database, and there is
+            // normally no reason to convert the value.
+            //
+            // However, if ind_ were ownInd_ itself, and if a prepared statement
+            // were repeatedly executed, we still need to do it in order to
+            // give the custom conversion a chance to update the indicator
+            // based on the actual value being used.
+            if (&ind_ != &(base_value_holder<T>::ownInd_))
+            {
+                // We really have nothing to do here, notably do not call the
+                // custom conversion which could overwrite the explicit i_null
+                // specified by the caller.
+                return;
+            }
+        }
+
+        type_conversion<T>::to_base(value_,
+            base_value_holder<T>::val_, ind_);
+    }
+
+private:
+    T & value_;
+
+    // ind_ refers to either ownInd_, or the one provided by the user
+    // in any case, ind_ refers to some valid indicator
+    // and can be used by conversion routines
+    indicator & ind_;
+
+    const bool readOnly_;
+
+    SOCI_NOT_COPYABLE(conversion_use_type)
+};
+
+// this class is used to ensure correct order of construction
+// of vector based into_type and use_type elements that use type_conversion
+
+template <typename T>
+struct base_vector_holder
+{
+    base_vector_holder(std::size_t sz = 0) : vec_(sz) {}
+    mutable std::vector<typename type_conversion<T>::base_type> vec_;
+};
+
+// Automatically create a std::vector based into_type from a type_conversion
+
+template <typename T>
+class conversion_into_type<std::vector<T> >
+    : private base_vector_holder<T>,
+      public into_type<std::vector<typename type_conversion<T>::base_type> >
+{
+public:
+    typedef typename std::vector
+        <
+            typename type_conversion<T>::base_type
+        > base_type;
+
+    conversion_into_type(std::vector<T> & value,
+        std::size_t begin = 0, std::size_t * end = NULL)
+        : base_vector_holder<T>(value.size()),
+        into_type<base_type>(
+            base_vector_holder<T>::vec_, ownInd_, begin, end),
+        value_(value),
+        ownInd_(),
+        ind_(ownInd_),
+        begin_(begin),
+        end_(end)
+    {
+        user_ranges_ = end != NULL;
+    }
+
+    conversion_into_type(std::vector<T> & value, std::vector<indicator> & ind,
+        std::size_t begin = 0, std::size_t * end = NULL)
+        : base_vector_holder<T>(value.size()),
+        into_type<base_type>(
+            base_vector_holder<T>::vec_, ind, begin, end),
+        value_(value),
+        ind_(ind),
+        begin_(begin),
+        end_(end)
+    {
+        user_ranges_ = end != NULL;
+    }
+
+    std::size_t size() const override
+    {
+        // the user might have resized his vector in the meantime
+        // -> synchronize the base-value mirror to have the same size
+
+        std::size_t const userSize = value_.size();
+        base_vector_holder<T>::vec_.resize(userSize);
+
+        return into_type<base_type>::size();
+    }
+
+    void resize(std::size_t sz) override
+    {
+        into_type<base_type>::resize(sz);
+
+        std::size_t actual_size = base_vector_holder<T>::vec_.size();
+        value_.resize(actual_size);
+        ind_.resize(actual_size);
+    }
+
+private:
+    void convert_from_base() override
+    {
+        if (user_ranges_)
+        {
+            for (std::size_t i = begin_; i != *end_; ++i)
+            {
+                type_conversion<T>::from_base(
+                    base_vector_holder<T>::vec_[i], ind_[i], value_[i]);
+            }
+        }
+        else
+        {
+            std::size_t const sz = base_vector_holder<T>::vec_.size();
+
+            for (std::size_t i = 0; i != sz; ++i)
+            {
+                type_conversion<T>::from_base(
+                    base_vector_holder<T>::vec_[i], ind_[i], value_[i]);
+            }
+        }
+    }
+
+    std::vector<T> & value_;
+
+    std::vector<indicator> ownInd_;
+
+    // ind_ refers to either ownInd_, or the one provided by the user
+    // in any case, ind_ refers to some valid vector of indicators
+    // and can be used by conversion routines
+    std::vector<indicator> & ind_;
+
+    std::size_t begin_;
+    std::size_t * end_;
+    bool user_ranges_;
+
+    SOCI_NOT_COPYABLE(conversion_into_type)
+};
+
+
+// Automatically create a std::vector based use_type from a type_conversion
+
+template <typename T>
+class conversion_use_type<std::vector<T> >
+     : private base_vector_holder<T>,
+       public use_type<std::vector<typename type_conversion<T>::base_type> >
+{
+public:
+    typedef typename std::vector
+        <
+            typename type_conversion<T>::base_type
+        > base_type;
+
+    conversion_use_type(const std::vector<T> & value,
+        std::string const & name=std::string())
+        : base_vector_holder<T>(value.size()),
+        use_type<base_type>(
+            base_vector_holder<T>::vec_, ownInd_, 0, NULL, name),
+        value_(value),
+        ownInd_(),
+        ind_(ownInd_),
+        begin_(0),
+        end_(NULL),
+        user_ranges_(false)
+    {
+    }
+
+    conversion_use_type(const std::vector<T> & value,
+        std::size_t begin, std::size_t * end,
+        std::string const & name=std::string())
+        : base_vector_holder<T>(value.size()),
+        use_type<base_type>(
+            base_vector_holder<T>::vec_, ownInd_, begin, end, name),
+        value_(value),
+        ownInd_(),
+        ind_(ownInd_),
+        begin_(begin),
+        end_(end)
+    {
+        user_ranges_ = end != NULL;
+    }
+
+    conversion_use_type(const std::vector<T> & value,
+        std::vector<indicator> & ind,
+        std::string const & name = std::string())
+        : base_vector_holder<T>(value.size()),
+        use_type<base_type>(
+            base_vector_holder<T>::vec_, ind, 0, NULL, name),
+        value_(value),
+        ind_(ind),
+        begin_(0),
+        end_(NULL),
+        user_ranges_(false)
+    {
+    }
+
+    conversion_use_type(const std::vector<T> & value,
+        std::vector<indicator> & ind,
+        std::size_t begin, std::size_t * end,
+        std::string const & name = std::string())
+        : base_vector_holder<T>(value.size()),
+        use_type<base_type>(
+            base_vector_holder<T>::vec_, ind, begin, end, name),
+        value_(value),
+        ind_(ind),
+        begin_(begin),
+        end_(end)
+    {
+        user_ranges_ = end != NULL;
+    }
+
+private:
+    void convert_to_base() override
+    {
+        std::size_t const sz = value_.size();
+        base_vector_holder<T>::vec_.resize(sz);
+        ind_.resize(sz);
+
+        if (user_ranges_)
+        {
+            for (std::size_t i = begin_; i != *end_; ++i)
+            {
+                type_conversion<T>::to_base(value_[i],
+                    base_vector_holder<T>::vec_[i], ind_[i]);
+            }
+        }
+        else
+        {
+            for (std::size_t i = 0; i != sz; ++i)
+            {
+                type_conversion<T>::to_base(value_[i],
+                    base_vector_holder<T>::vec_[i], ind_[i]);
+            }
+        }
+    }
+
+    const std::vector<T> & value_;
+
+    std::vector<indicator> ownInd_;
+
+    // ind_ refers to either ownInd_, or the one provided by the user
+    // in any case, ind_ refers to some valid vector of indicators
+    // and can be used by conversion routines
+    std::vector<indicator> & ind_;
+
+    std::size_t begin_;
+    std::size_t * end_;
+    bool user_ranges_;
+
+    SOCI_NOT_COPYABLE(conversion_use_type)
+};
+
+template <typename T>
+into_type_ptr do_into(T & t, user_type_tag)
+{
+    return into_type_ptr(new conversion_into_type<T>(t));
+}
+
+template <typename T>
+into_type_ptr do_into(T & t, indicator & ind, user_type_tag)
+{
+    return into_type_ptr(new conversion_into_type<T>(t, ind));
+}
+
+template <typename T>
+into_type_ptr do_into(std::vector<T> & t,
+    std::size_t begin, size_t * end, user_type_tag)
+{
+    return into_type_ptr(
+        new conversion_into_type<std::vector<T> >(t, begin, end));
+}
+
+template <typename T>
+into_type_ptr do_into(std::vector<T> & t, std::vector<indicator> & ind,
+    user_type_tag)
+{
+    return into_type_ptr(new conversion_into_type<std::vector<T> >(t, ind));
+}
+
+template <typename T>
+into_type_ptr do_into(std::vector<T> & t, std::vector<indicator> & ind,
+    std::size_t begin, size_t * end, user_type_tag)
+{
+    return into_type_ptr(
+        new conversion_into_type<std::vector<T> >(t, ind, begin, end));
+}
+
+template <typename T>
+use_type_ptr do_use(T & t, std::string const & name, user_type_tag)
+{
+    return use_type_ptr(new conversion_use_type<T>(t, name));
+}
+
+template <typename T>
+use_type_ptr do_use(T const & t, std::string const & name, user_type_tag)
+{
+    return use_type_ptr(new conversion_use_type<T>(t, name));
+}
+
+template <typename T>
+use_type_ptr do_use(T & t, indicator & ind,
+    std::string const & name, user_type_tag)
+{
+    return use_type_ptr(new conversion_use_type<T>(t, ind, name));
+}
+
+template <typename T>
+use_type_ptr do_use(T const & t, indicator & ind,
+    std::string const & name, user_type_tag)
+{
+    return use_type_ptr(new conversion_use_type<T>(t, ind, name));
+}
+
+template <typename T>
+use_type_ptr do_use(std::vector<T> & t,
+    std::size_t begin, size_t * end,
+    std::string const & name, user_type_tag)
+{
+    return use_type_ptr(
+        new conversion_use_type<std::vector<T> >(t, begin, end, name));
+}
+
+template <typename T>
+use_type_ptr do_use(const std::vector<T> & t,
+    std::size_t begin, size_t * end,
+    std::string const & name, user_type_tag)
+{
+    return use_type_ptr(
+        new conversion_use_type<std::vector<T> >(t, begin, end, name));
+}
+
+template <typename T>
+use_type_ptr do_use(std::vector<T> & t, std::vector<indicator> & ind,
+    std::size_t begin, size_t * end,
+    std::string const & name, user_type_tag)
+{
+    return use_type_ptr(
+        new conversion_use_type<std::vector<T> >(t, ind, begin, end, name));
+}
+
+template <typename T>
+use_type_ptr do_use(const std::vector<T> & t, std::vector<indicator> & ind,
+    std::size_t begin, size_t * end,
+    std::string const & name, user_type_tag)
+{
+    return use_type_ptr(
+        new conversion_use_type<std::vector<T> >(t, ind, begin, end, name));
+}
+
+} // namespace details
+
+} // namespace soci
+
+#endif // SOCI_TYPE_CONVERSION_H_INCLUDED

+ 449 - 0
3rdparty/soci/include/soci/type-holder.h

@@ -0,0 +1,449 @@
+//
+// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_TYPE_HOLDER_H_INCLUDED
+#define SOCI_TYPE_HOLDER_H_INCLUDED
+
+#include "soci/blob.h"
+#include "soci/error.h"
+#include "soci/soci-backend.h"
+#include "soci/soci-types.h"
+
+#include <cstdint>
+#include <ctime>
+#include <limits>
+#include <sstream>
+#include <type_traits>
+#include <typeinfo>
+
+namespace soci
+{
+
+namespace details
+{
+
+// Returns U* as T*, if the dynamic type of the pointer is really T.
+//
+// This should be used instead of dynamic_cast<> because using it doesn't work
+// when using libc++ and ELF visibility together. Luckily, when we don't need
+// the full power of the cast, but only need to check if the types are the
+// same, it can be done by comparing their type info objects.
+//
+// This function does _not_ replace dynamic_cast<> in all cases and notably
+// doesn't allow the input pointer to be null.
+template <typename T, typename U>
+T* checked_ptr_cast(U* ptr)
+{
+    // Check if they're identical first, as an optimization, and then compare
+    // their names to make it actually work with libc++.
+    std::type_info const& ti_ptr = typeid(*ptr);
+    std::type_info const& ti_ret = typeid(T);
+
+    if (&ti_ptr != &ti_ret && std::strcmp(ti_ptr.name(), ti_ret.name()) != 0)
+    {
+        return NULL;
+    }
+
+    return static_cast<T*>(ptr);
+}
+
+template <typename T, typename U, typename Enable = void>
+struct soci_return_same
+{
+    static inline T& value(U&)
+    {
+        throw std::bad_cast();
+    }
+};
+
+template <typename T, typename U>
+struct soci_return_same<
+    T, U,
+    typename std::enable_if<std::is_same<T, U>::value>::type>
+{
+    static inline T& value(U& val)
+    {
+        return val;
+    }
+};
+
+// Type safe conversion that throws if the types are mismatched
+template <typename T, typename U, typename Enable = void>
+struct soci_cast
+{
+    static inline T cast(U)
+    {
+        throw std::bad_cast();
+    }
+};
+
+// Type safe conversion that is a noop
+template <typename T, typename U>
+struct soci_cast<
+    T, U,
+    typename std::enable_if<std::is_same<T, U>::value>::type>
+{
+    static inline T cast(U val)
+    {
+        return val;
+    }
+};
+
+// Type safe conversion that is widening the type
+template <typename T, typename U>
+struct soci_cast<
+    T, U,
+    typename std::enable_if<(
+        !std::is_same<T, U>::value &&
+        std::is_integral<T>::value &&
+        std::is_integral<U>::value
+    )>::type>
+{
+    static inline T cast(U val) {
+        intmax_t t_min = static_cast<intmax_t>((std::numeric_limits<T>::min)());
+        intmax_t u_min = static_cast<intmax_t>((std::numeric_limits<U>::min)());
+        uintmax_t t_max = static_cast<uintmax_t>((std::numeric_limits<T>::max)());
+        uintmax_t u_max = static_cast<uintmax_t>((std::numeric_limits<U>::max)());
+
+#ifdef _MSC_VER
+// As long as we don't require C++17, we must disable the warning
+// "conditional expression is constant" as it can give false positives here.
+#pragma warning(push)
+#pragma warning(disable:4127)
+#endif
+        if ((t_min > u_min && val < static_cast<U>(t_min)) ||
+            (t_max < u_max && val > static_cast<U>(t_max)))
+        {
+            throw std::bad_cast();
+        }
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+        return static_cast<T>(val);
+    }
+};
+
+union type_holder
+{
+    std::string* s;
+    int8_t* i8;
+    int16_t* i16;
+    int32_t* i32;
+    int64_t* i64;
+    uint8_t* u8;
+    uint16_t* u16;
+    uint32_t* u32;
+    uint64_t* u64;
+    double* d;
+    std::tm* t;
+    blob* b;
+};
+
+template <typename T>
+struct type_holder_trait;
+
+template <>
+struct type_holder_trait<std::string>
+{
+    static const db_type type = db_string;
+};
+
+template <>
+struct type_holder_trait<int8_t>
+{
+    static const db_type type = db_int8;
+};
+
+template <>
+struct type_holder_trait<int16_t>
+{
+    static const db_type type = db_int16;
+};
+
+template <>
+struct type_holder_trait<int32_t>
+{
+    static const db_type type = db_int32;
+};
+
+template <>
+struct type_holder_trait<int64_t>
+{
+    static const db_type type = db_int64;
+};
+
+template <>
+struct type_holder_trait<uint8_t>
+{
+    static const db_type type = db_uint8;
+};
+
+template <>
+struct type_holder_trait<uint16_t>
+{
+    static const db_type type = db_uint16;
+};
+
+template <>
+struct type_holder_trait<uint32_t>
+{
+    static const db_type type = db_uint32;
+};
+
+template <>
+struct type_holder_trait<uint64_t>
+{
+    static const db_type type = db_uint64;
+};
+
+#if defined(SOCI_INT64_IS_LONG)
+template <>
+struct type_holder_trait<long long> : type_holder_trait<int64_t>
+{
+};
+
+template <>
+struct type_holder_trait<unsigned long long> : type_holder_trait<uint64_t>
+{
+};
+#elif defined(SOCI_LONG_IS_64_BIT)
+template <>
+struct type_holder_trait<long> : type_holder_trait<int64_t>
+{
+};
+
+template <>
+struct type_holder_trait<unsigned long> : type_holder_trait<uint64_t>
+{
+};
+#else
+template <>
+struct type_holder_trait<long> : type_holder_trait<int32_t>
+{
+};
+
+template <>
+struct type_holder_trait<unsigned long> : type_holder_trait<uint32_t>
+{
+};
+#endif
+
+template <>
+struct type_holder_trait<double>
+{
+    static const db_type type = db_double;
+};
+
+template <>
+struct type_holder_trait<std::tm>
+{
+    static const db_type type = db_date;
+};
+
+template <>
+struct type_holder_trait<blob>
+{
+    static const db_type type = db_blob;
+};
+
+struct value_cast_tag{};
+struct value_reference_tag{};
+
+// Class for storing type data instances in a container of holder objects
+class holder
+{
+public:
+    template <typename T>
+    static holder* make_holder(T* val)
+    {
+         return new holder(type_holder_trait<T>::type, val);
+    }
+
+    ~holder()
+    {
+        switch (dt_)
+        {
+        case db_double:
+            delete val_.d;
+            break;
+        case db_int8:
+            delete val_.i8;
+            break;
+        case db_int16:
+            delete val_.i16;
+            break;
+        case db_int32:
+            delete val_.i32;
+            break;
+        case db_int64:
+            delete val_.i64;
+            break;
+        case db_uint8:
+            delete val_.u8;
+            break;
+        case db_uint16:
+            delete val_.u16;
+            break;
+        case db_uint32:
+            delete val_.u32;
+            break;
+        case db_uint64:
+            delete val_.u64;
+            break;
+        case db_date:
+            delete val_.t;
+            break;
+        case db_blob:
+            delete val_.b;
+            break;
+        case db_xml:
+        case db_string:
+            delete val_.s;
+            break;
+        }
+    }
+
+#ifdef _MSC_VER
+// MSVC complains about "unreachable code" even though all
+// code here can be reached.
+#pragma warning(push)
+#pragma warning(disable:4702)
+#endif
+    template <typename T>
+    T get(value_cast_tag)
+    {
+        switch (dt_)
+        {
+        case db_int8:
+            return soci_cast<T, int8_t>::cast(*val_.i8);
+        case db_int16:
+            return soci_cast<T, int16_t>::cast(*val_.i16);
+        case db_int32:
+            return soci_cast<T, int32_t>::cast(*val_.i32);
+        case db_int64:
+            return soci_cast<T, int64_t>::cast(*val_.i64);
+        case db_uint8:
+            return soci_cast<T, uint8_t>::cast(*val_.u8);
+        case db_uint16:
+            return soci_cast<T, uint16_t>::cast(*val_.u16);
+        case db_uint32:
+            return soci_cast<T, uint32_t>::cast(*val_.u32);
+        case db_uint64:
+            return soci_cast<T, uint64_t>::cast(*val_.u64);
+        case db_double:
+            return soci_cast<T, double>::cast(*val_.d);
+        case db_date:
+            return soci_cast<T, std::tm>::cast(*val_.t);
+        case db_blob:
+            // blob is not copyable
+            break;
+        case db_xml:
+        case db_string:
+            return soci_cast<T, std::string>::cast(*val_.s);
+        }
+
+        throw std::bad_cast();
+    }
+
+    template <typename T>
+    T& get(value_reference_tag)
+    {
+        switch (dt_)
+        {
+        case db_int8:
+            return soci_return_same<T, int8_t>::value(*val_.i8);
+        case db_int16:
+            return soci_return_same<T, int16_t>::value(*val_.i16);
+        case db_int32:
+            return soci_return_same<T, int32_t>::value(*val_.i32);
+        case db_int64:
+            return soci_return_same<T, int64_t>::value(*val_.i64);
+        case db_uint8:
+            return soci_return_same<T, uint8_t>::value(*val_.u8);
+        case db_uint16:
+            return soci_return_same<T, uint16_t>::value(*val_.u16);
+        case db_uint32:
+            return soci_return_same<T, uint32_t>::value(*val_.u32);
+        case db_uint64:
+            return soci_return_same<T, uint64_t>::value(*val_.u64);
+        case db_double:
+            return soci_return_same<T, double>::value(*val_.d);
+        case db_date:
+            return soci_return_same<T, std::tm>::value(*val_.t);
+        case db_blob:
+            return soci_return_same<T, blob>::value(*val_.b);
+        case db_xml:
+        case db_string:
+            return soci_return_same<T, std::string>::value(*val_.s);
+        }
+
+        throw std::bad_cast();
+    }
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+private:
+    holder(db_type dt, void* val) : dt_(dt)
+    {
+        switch (dt_)
+        {
+        case db_double:
+            val_.d = static_cast<double*>(val);
+            return;
+        case db_int8:
+            val_.i8 = static_cast<int8_t*>(val);
+            return;
+        case db_int16:
+            val_.i16 = static_cast<int16_t*>(val);
+            return;
+        case db_int32:
+            val_.i32 = static_cast<int32_t*>(val);
+            return;
+        case db_int64:
+            val_.i64 = static_cast<int64_t*>(val);
+            return;
+        case db_uint8:
+            val_.u8 = static_cast<uint8_t*>(val);
+            return;
+        case db_uint16:
+            val_.u16 = static_cast<uint16_t*>(val);
+            return;
+        case db_uint32:
+            val_.u32 = static_cast<uint32_t*>(val);
+            return;
+        case db_uint64:
+            val_.u64 = static_cast<uint64_t*>(val);
+            return;
+        case db_date:
+            val_.t = static_cast<std::tm*>(val);
+            return;
+        case db_blob:
+            val_.b = static_cast<blob*>(val);
+            return;
+        case db_xml:
+        case db_string:
+            val_.s = static_cast<std::string*>(val);
+            return;
+        }
+
+        // This should be unreachable
+        std::ostringstream ss;
+        ss << "Created holder with unsupported type " << std::to_string(dt);
+        throw soci_error(ss.str());
+    }
+
+    const db_type dt_;
+    type_holder val_;
+};
+
+} // namespace details
+
+} // namespace soci
+
+#endif // SOCI_TYPE_HOLDER_H_INCLUDED

+ 30 - 0
3rdparty/soci/include/soci/type-ptr.h

@@ -0,0 +1,30 @@
+//
+// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_TYPE_PTR_H_INCLUDED
+#define SOCI_TYPE_PTR_H_INCLUDED
+
+namespace soci { namespace details {
+
+template <typename T>
+class type_ptr
+{
+public:
+    type_ptr(T * p) : p_(p) {}
+    ~type_ptr() { delete p_; }
+
+    T * get() const { return p_; }
+    void release() const { p_ = 0; }
+
+private:
+    mutable T * p_;
+};
+
+} // namespace details
+} // namespace soci
+
+#endif // SOCI_TYPE_PTR_H_INCLUDED

+ 33 - 0
3rdparty/soci/include/soci/type-wrappers.h

@@ -0,0 +1,33 @@
+//
+// Copyright (C) 2016 Maciej Sobczak
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_TYPE_WRAPPERS_H_INCLUDED
+#define SOCI_TYPE_WRAPPERS_H_INCLUDED
+
+namespace soci
+{
+
+// These wrapper types can be used by the application
+// with 'into' and 'use' elements in order to guide the library
+// in selecting specialized methods for binding and transferring data;
+// if the target database does not provide any such specialized methods,
+// it is expected to handle these wrappers as equivalent
+// to their contained field types.
+
+struct xml_type
+{
+    std::string value;
+};
+
+struct long_string
+{
+    std::string value;
+};
+
+} // namespace soci
+
+#endif // SOCI_TYPE_WRAPPERS_H_INCLUDED

+ 340 - 0
3rdparty/soci/include/soci/use-type.h

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

+ 123 - 0
3rdparty/soci/include/soci/use.h

@@ -0,0 +1,123 @@
+//
+// Copyright (C) 2004-2016 Maciej Sobczak, Stephen Hutton
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_USE_H_INCLUDED
+#define SOCI_USE_H_INCLUDED
+
+#include "soci/use-type.h"
+#include "soci/exchange-traits.h"
+#include "soci/type-conversion.h"
+#include "soci/soci-backend.h"
+
+namespace soci
+{
+
+namespace details
+{
+template <typename T, typename Indicator>
+struct use_container
+{
+    use_container(T &_t, Indicator &_ind, const std::string &_name)
+        : t(_t), ind(_ind), name(_name) {}
+
+    T &t;
+    Indicator &ind;
+    const std::string &name;
+private:
+    SOCI_NOT_ASSIGNABLE(use_container)
+};
+
+typedef void no_indicator;
+template <typename T>
+struct use_container<T, no_indicator>
+{
+    use_container(T &_t, const std::string &_name)
+        : t(_t), name(_name) {}
+
+    T &t;
+    const std::string &name;
+private:
+    SOCI_NOT_ASSIGNABLE(use_container)
+};
+
+} // namespace details
+
+// soci::use is deleted for rvalues because it will likely lead to subtle stack-use-after-scope bugs.
+template <typename T>
+details::use_container<T, details::no_indicator> use(T &&t, const std::string &name = std::string()) = delete;
+
+template <typename T>
+details::use_container<const T, indicator> use(T &&t, indicator & ind, std::string const &name = std::string()) = delete;
+
+template <typename T>
+details::use_container<T, details::no_indicator> use(T &t, const std::string &name = std::string())
+{ return details::use_container<T, details::no_indicator>(t, name); }
+
+template <typename T>
+details::use_container<const T, details::no_indicator> use(T const &t, const std::string &name = std::string())
+{ return details::use_container<const T, details::no_indicator>(t, name); }
+
+template <typename T>
+details::use_container<T, indicator> use(T &t, indicator & ind, std::string const &name = std::string())
+{ return details::use_container<T, indicator>(t, ind, name); }
+
+template <typename T>
+details::use_container<const T, indicator> use(T const &t, indicator & ind, std::string const &name = std::string())
+{ return details::use_container<const T, indicator>(t, ind, name); }
+
+// vector containers
+template <typename T>
+details::use_container<T, std::vector<indicator> >
+    use(T &t, std::vector<indicator> & ind, const std::string &name = std::string())
+{ return details::use_container<T, std::vector<indicator> >(t, ind, name); }
+
+template <typename T>
+details::use_container<std::vector<T>, details::no_indicator >
+    use(std::vector<T> &t, const std::string &name = std::string())
+{ return details::use_container<std::vector<T>, details::no_indicator>(t, name); }
+
+// vectors with index ranges
+
+template <typename T>
+details::use_type_ptr use(std::vector<T> & t,
+    std::size_t begin, std::size_t & end,
+    const std::string &name = std::string())
+{
+    return details::do_use(t, begin, &end, name,
+        typename details::exchange_traits<std::vector<T> >::type_family());
+}
+
+template <typename T>
+details::use_type_ptr use(const std::vector<T> & t,
+    std::size_t begin, std::size_t & end,
+    const std::string &name = std::string())
+{
+    return details::do_use(t, begin, &end, name,
+        typename details::exchange_traits<std::vector<T> >::type_family());
+}
+
+template <typename T>
+details::use_type_ptr use(std::vector<T> & t, std::vector<indicator> & ind,
+    std::size_t begin, std::size_t & end,
+    const std::string &name = std::string())
+{
+    return details::do_use(t, ind, begin, &end, name,
+        typename details::exchange_traits<std::vector<T> >::type_family());
+}
+
+template <typename T>
+details::use_type_ptr use(const std::vector<T> & t, std::vector<indicator> & ind,
+    std::size_t begin, std::size_t & end,
+    const std::string &name = std::string())
+{
+    return details::do_use(t, ind, begin, &end, name,
+        typename details::exchange_traits<std::vector<T> >::type_family());
+}
+
+} // namespace soci
+
+#endif // SOCI_USE_H_INCLUDED

+ 150 - 0
3rdparty/soci/include/soci/values-exchange.h

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

+ 351 - 0
3rdparty/soci/include/soci/values.h

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

+ 34 - 0
3rdparty/soci/include/soci/version.h

@@ -0,0 +1,34 @@
+//  SOCI version.hpp configuration header file
+
+//
+// Copyright (C) 2011 Mateusz Loskot <mateusz@loskot.net>
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SOCI_VERSION_HPP
+#define SOCI_VERSION_HPP
+
+// When updating the version here, don't forget to update it in CMakeLists.txt!
+
+//
+//  Caution, this is the only SOCI header that is guarenteed
+//  to change with every SOCI release, including this header
+//  will cause a recompile every time a new SOCI version is
+//  released.
+//
+//  SOCI_VERSION % 100 is the patch level
+//  SOCI_VERSION / 100 % 1000 is the minor version
+//  SOCI_VERSION / 100000 is the major version
+
+#define SOCI_VERSION 400100
+
+//
+//  SOCI_LIB_VERSION must be defined to be the same as SOCI_VERSION
+//  but as a *string* in the form "x_y[_z]" where x is the major version
+//  number, y is the minor version number, and z is the patch level if not 0.
+
+#define SOCI_LIB_VERSION "4_1_0"
+
+#endif // SOCI_VERSION_HPP

+ 1 - 1
3rdparty/ylib/include/util/ini.h

@@ -13,7 +13,7 @@ namespace ylib
 		void close();
         std::string read(const std::string& name,const std::string& key,const std::string& default_value = "") const;
         bool write(const std::string& name,const std::string& key,const std::string& value);
-#ifndef _WIN32
+#ifndef _WIN321
 		bool del(const std::string& name, const std::string& key);
 
 		// 一级NAME

+ 3 - 2
config.ini

@@ -17,7 +17,7 @@ auto_update_sec=3
 
 [website]
 ; 网站静态文件目录
-static_dir=${base}/root
+static_dir=${base}/www
 ; 默认页面-404
 default_404=page/404.html
 ; 默认首页(index.html,index.htm,index.lua)
@@ -30,7 +30,8 @@ session_timeout_sec=86400
 Initialization_script=${base}/scripts/init.lua
 ; 拦截器
 interceptor_scripts= [["${base}/scripts/interceptor.lua","/scripts/*.*"]]
-
+; 调试模式,开启后控制台输出异常错误信息 (0=关闭 1=开启)
+debug=1
 [server]
 ; TCP服务监听地址
 address=0.0.0.0

+ 18 - 13
fastweb.vcxproj

@@ -25,12 +25,17 @@
     <ClCompile Include="src\core\global.cpp" />
     <ClCompile Include="src\core\main.cpp" />
     <ClCompile Include="src\core\statemanager.cpp" />
+    <ClCompile Include="src\module\codec.cpp" />
     <ClCompile Include="src\module\globalfuns.cpp" />
+    <ClCompile Include="src\module\http\httpclient.cpp" />
     <ClCompile Include="src\module\http\request.cpp" />
     <ClCompile Include="src\module\http\response.cpp" />
     <ClCompile Include="src\module\http\session.cpp" />
     <ClCompile Include="src\module\localstorage.cpp" />
+    <ClCompile Include="src\module\mssql.cpp" />
+    <ClCompile Include="src\module\mutex.cpp" />
     <ClCompile Include="src\module\mysql.cpp" />
+    <ClCompile Include="src\module\time.cpp" />
     <ClCompile Include="src\utils\logutils.cpp" />
     <ClCompile Include="src\utils\luautils.cpp" />
   </ItemGroup>
@@ -42,13 +47,18 @@
     <ClInclude Include="src\core\global.h" />
     <ClInclude Include="src\core\statemanager.h" />
     <ClInclude Include="src\core\structs.h" />
+    <ClInclude Include="src\module\codec.h" />
     <ClInclude Include="src\module\globalfuns.h" />
+    <ClInclude Include="src\module\http\httpclient.h" />
     <ClInclude Include="src\module\http\request.h" />
     <ClInclude Include="src\module\http\response.h" />
     <ClInclude Include="src\module\http\session.h" />
     <ClInclude Include="src\module\imodule.h" />
     <ClInclude Include="src\module\localstorage.h" />
+    <ClInclude Include="src\module\mssql.h" />
+    <ClInclude Include="src\module\mutex.h" />
     <ClInclude Include="src\module\mysql.h" />
+    <ClInclude Include="src\module\time.h" />
     <ClInclude Include="src\utils\logutils.h" />
     <ClInclude Include="src\utils\luautils.h" />
   </ItemGroup>
@@ -56,11 +66,6 @@
     <None Include=".gitignore" />
     <None Include="config.ini" />
     <None Include="README.md" />
-    <None Include="scripts\app\index.lua" />
-    <None Include="scripts\init.lua" />
-    <None Include="scripts\interceptor.lua" />
-    <None Include="scripts\lib\dkjson.lua" />
-    <None Include="scripts\lib\website.lua" />
   </ItemGroup>
   <ItemGroup>
     <Text Include="LICENSE.txt" />
@@ -156,18 +161,18 @@
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
     <ClCompile>
       <WarningLevel>Level3</WarningLevel>
-      <SDLCheck>true</SDLCheck>
+      <SDLCheck>false</SDLCheck>
       <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ConformanceMode>true</ConformanceMode>
-      <AdditionalIncludeDirectories>$(SolutionDir)src;$(SolutionDir)3rdparty;$(SolutionDir)3rdparty\lua;$(SolutionDir)3rdparty\ylib\include;$(SolutionDir)3rdparty\HP-Socket\include</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(SolutionDir)3rdparty\soci\include;$(SolutionDir)src;$(SolutionDir)3rdparty;$(SolutionDir)3rdparty\lua;D:\lib\ylib\include;$(SolutionDir)3rdparty\HP-Socket\include</AdditionalIncludeDirectories>
       <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
       <LanguageStandard>stdcpp20</LanguageStandard>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>User32.lib;Advapi32.lib;IPHLPAPI.lib;WS2_32.lib;Shell32.lib;leveldb.lib;libzip.lib;lua.lib;sqlite3.lib;ylib.lib;zlib.lib;mysqlcppconn.lib;HPSocket_D.lib;libcrypto_static.lib</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(SolutionDir)3rdparty\ylib\lib\$(Configuration);$(SolutionDir)3rdparty\mysql\lib\$(Configuration);$(SolutionDir)3rdparty\HP-Socket\lib;$(SolutionDir)3rdparty</AdditionalLibraryDirectories>
+      <AdditionalDependencies>libsoci_core_4_1.lib;libsoci_empty_4_1.lib;libsoci_odbc_4_1.lib;soci_core_4_1.lib;soci_empty_4_1.lib;soci_odbc_4_1.lib;odbc32.lib;User32.lib;Advapi32.lib;IPHLPAPI.lib;WS2_32.lib;Shell32.lib;leveldb.lib;libzip.lib;lua.lib;sqlite3.lib;D:\lib\ylib_vs_build\lib\Debug\ylib.lib;zlib.lib;mysqlcppconn.lib;HPSocket_D.lib;libcrypto_static.lib</AdditionalDependencies>
+      <AdditionalLibraryDirectories>$(SolutionDir)3rdparty\ylib\lib\$(Configuration);$(SolutionDir)3rdparty\mysql\lib\$(Configuration);$(SolutionDir)3rdparty\HP-Socket\lib;$(SolutionDir)3rdparty;$(SolutionDir)3rdparty\soci\lib\$(Configuration)</AdditionalLibraryDirectories>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -175,10 +180,10 @@
       <WarningLevel>Level3</WarningLevel>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
+      <SDLCheck>false</SDLCheck>
       <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ConformanceMode>true</ConformanceMode>
-      <AdditionalIncludeDirectories>$(SolutionDir)src;$(SolutionDir)3rdparty;$(SolutionDir)3rdparty\lua;$(SolutionDir)3rdparty\ylib\include;$(SolutionDir)3rdparty\HP-Socket\include</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(SolutionDir)3rdparty\soci\include;$(SolutionDir)src;$(SolutionDir)3rdparty;$(SolutionDir)3rdparty\lua;D:\lib\ylib\include;$(SolutionDir)3rdparty\HP-Socket\include</AdditionalIncludeDirectories>
       <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
       <LanguageStandard>stdcpp20</LanguageStandard>
     </ClCompile>
@@ -187,8 +192,8 @@
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>User32.lib;Advapi32.lib;IPHLPAPI.lib;WS2_32.lib;Shell32.lib;leveldb.lib;libzip.lib;lua.lib;sqlite3.lib;ylib.lib;zlib.lib;mysqlcppconn.lib;HPSocket.lib;libcrypto_static.lib</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(SolutionDir)3rdparty\ylib\lib\$(Configuration);$(SolutionDir)3rdparty\mysql\lib\$(Configuration);$(SolutionDir)3rdparty\HP-Socket\lib;$(SolutionDir)3rdparty</AdditionalLibraryDirectories>
+      <AdditionalDependencies>libsoci_core_4_1.lib;libsoci_empty_4_1.lib;libsoci_odbc_4_1.lib;soci_core_4_1.lib;soci_empty_4_1.lib;soci_odbc_4_1.lib;odbc32.lib;User32.lib;Advapi32.lib;IPHLPAPI.lib;WS2_32.lib;Shell32.lib;leveldb.lib;libzip.lib;lua.lib;sqlite3.lib;ylib.lib;zlib.lib;mysqlcppconn.lib;HPSocket.lib;libcrypto_static.lib</AdditionalDependencies>
+      <AdditionalLibraryDirectories>$(SolutionDir)3rdparty\ylib\lib\$(Configuration);$(SolutionDir)3rdparty\mysql\lib\$(Configuration);$(SolutionDir)3rdparty\HP-Socket\lib;$(SolutionDir)3rdparty;$(SolutionDir)3rdparty\soci\lib\$(Configuration)</AdditionalLibraryDirectories>
     </Link>
   </ItemDefinitionGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+ 30 - 24
fastweb.vcxproj.filters

@@ -10,15 +10,6 @@
     <Filter Include="src\module">
       <UniqueIdentifier>{feb78a4c-cec1-4b7c-850b-6d1451e57962}</UniqueIdentifier>
     </Filter>
-    <Filter Include="scripts">
-      <UniqueIdentifier>{6f9c72e6-2a8a-4407-a277-1c83c92fd6b9}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="scripts\app">
-      <UniqueIdentifier>{cfc62d45-db7b-4cb5-9d11-8caf2977dfb2}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="scripts\lib">
-      <UniqueIdentifier>{573b85d6-db05-4a81-af04-172fe83306e5}</UniqueIdentifier>
-    </Filter>
     <Filter Include="src\utils">
       <UniqueIdentifier>{2b04f1f8-4027-4d87-a828-f18f2b918b8f}</UniqueIdentifier>
     </Filter>
@@ -69,6 +60,21 @@
     <ClCompile Include="src\module\globalfuns.cpp">
       <Filter>src\module</Filter>
     </ClCompile>
+    <ClCompile Include="src\module\mutex.cpp">
+      <Filter>src\module</Filter>
+    </ClCompile>
+    <ClCompile Include="src\module\codec.cpp">
+      <Filter>src\module</Filter>
+    </ClCompile>
+    <ClCompile Include="src\module\mssql.cpp">
+      <Filter>src\module</Filter>
+    </ClCompile>
+    <ClCompile Include="src\module\time.cpp">
+      <Filter>src\module</Filter>
+    </ClCompile>
+    <ClCompile Include="src\module\http\httpclient.cpp">
+      <Filter>src\module\http</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\core\fastweb.h">
@@ -119,24 +125,24 @@
     <ClInclude Include="src\module\globalfuns.h">
       <Filter>src\module</Filter>
     </ClInclude>
+    <ClInclude Include="src\module\mutex.h">
+      <Filter>src\module</Filter>
+    </ClInclude>
+    <ClInclude Include="src\module\codec.h">
+      <Filter>src\module</Filter>
+    </ClInclude>
+    <ClInclude Include="src\module\mssql.h">
+      <Filter>src\module</Filter>
+    </ClInclude>
+    <ClInclude Include="src\module\time.h">
+      <Filter>src\module</Filter>
+    </ClInclude>
+    <ClInclude Include="src\module\http\httpclient.h">
+      <Filter>src\module\http</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="config.ini" />
-    <None Include="scripts\app\index.lua">
-      <Filter>scripts\app</Filter>
-    </None>
-    <None Include="scripts\lib\dkjson.lua">
-      <Filter>scripts\lib</Filter>
-    </None>
-    <None Include="scripts\lib\website.lua">
-      <Filter>scripts\lib</Filter>
-    </None>
-    <None Include="scripts\init.lua">
-      <Filter>scripts</Filter>
-    </None>
-    <None Include="scripts\interceptor.lua">
-      <Filter>scripts</Filter>
-    </None>
     <None Include="README.md" />
     <None Include=".gitignore" />
   </ItemGroup>

+ 1 - 0
src/core/config.cpp

@@ -64,6 +64,7 @@ void config::cache()
 	website.session_dir = m_ini.read("website", "session_dir");
 	website.session_timeout_sec = ylib::stoi(m_ini.read("website", "session_timeout_sec"));
 	website.Initialization_script = m_ini.read("website", "Initialization_script");
+	website.debug = m_ini.read("website", "debug") == "1";
 
 	{
 		ylib::json interceptors = ylib::json::from(m_ini.read("website", "interceptor_scripts"));

+ 1 - 0
src/core/config.h

@@ -24,6 +24,7 @@ public:
 		uint32 session_timeout_sec;
 		std::string Initialization_script;
 		std::vector<__interceptor> interceptor_scripts;
+		bool debug = false;
 	};
 	struct server {
 		std::string address;

+ 2 - 2
src/core/define.h

@@ -1,6 +1,6 @@
 #pragma once
 #include <functional>
-
+#include <mutex>
 #include "sol/sol.hpp"
 
 #include "base/define.h"
@@ -27,4 +27,4 @@
 
 
 
-using VarType = std::variant<std::monostate,int, double, std::string,long long>;
+#define VarType sol::object

+ 6 - 1
src/core/fastweb.cpp

@@ -55,7 +55,8 @@ bool fastweb::start()
 		for_iter(iter, luas) {
 			if (iter->second == IS_DIRECTORY)
 				continue;
-			if (service_bytecode.create(iter->first, sConfig->scripts.app_dir + "/" + iter->first, true) == false)
+			std::string path = strutils::replace(iter->first, '\\', '/');
+			if (service_bytecode.create(path, sConfig->scripts.app_dir + "/" + path, true) == false)
 			{
 				m_lastErrorDesc = service_bytecode.last_error();
 				return false;
@@ -190,6 +191,8 @@ void fastweb::subscribe_service(network::http::request* request, network::http::
 	catch (const std::exception& e)
 	{
 		exception_string = e.what();
+		if(sConfig->website.debug)
+			LOG_ERROR("[subscribe_service]["+ request->filepath() + "]: "+e.what());
 	}
 	lua->collect_garbage();
 	sStateMgr->push_state(lua);
@@ -234,6 +237,8 @@ bool fastweb::subscribe_interceptor(network::http::reqpack* reqpack, const std::
 	catch (const std::exception& e)
 	{
 		exception_string = e.what();
+		if (sConfig->website.debug)
+			LOG_ERROR("[subscribe_interceptor][" + reqpack->request()->filepath() + "]: " + e.what());
 	}
 	sStateMgr->push_state(lua);
 

+ 15 - 0
src/core/global.cpp

@@ -28,3 +28,18 @@ bool global::regist_ptr(const std::string& name, void* value, sol::this_state ts
 	}
 	return m_value_ptr.add(name, value);
 }
+
+VarType global::get(const std::string& name, sol::this_state s)
+{
+	VarType value;
+	if (m_values.get(name, value))
+	{
+		return value;
+	}
+	return sol::make_object(s, sol::nil);
+}
+
+void global::set(const std::string& name, VarType value)
+{
+	m_values.set(name, value, true);
+}

+ 6 - 1
src/core/global.h

@@ -13,7 +13,12 @@ public:
 	bool regist_ptr(const std::string& name,void* value, sol::this_state ts);
 
 
+	VarType get(const std::string& name, sol::this_state s);
+	void set(const std::string& name,VarType value);
 
 private:
 	ylib::map<std::string, void*> m_value_ptr;
-};
+
+	ylib::map<std::string,VarType> m_values;
+};
+

+ 2 - 2
src/core/main.cpp

@@ -11,13 +11,13 @@ int main()
 
 	if(sConfig->open(system::current_dir() + "\\config.ini") == false)
 	{
-		LOG_ERROR(sConfig->last_error());
+		LOG_ERROR("open config failed,"+sConfig->last_error());
 		return -1;
 	}
 
 	if (fastweb::getInstance()->start() == false)
 	{
-		LOG_ERROR(fastweb::getInstance()->last_error());
+		LOG_ERROR("fastweb start failed,"+fastweb::getInstance()->last_error());
 		return -1;
 	}
 

+ 34 - 4
src/core/statemanager.cpp

@@ -1,16 +1,25 @@
 #include "statemanager.h"
+
 #include "util/file.h"
 #include "util/system.h"
 #include "util/time.h"
+
+#include "core/define.h"
+#include "core/config.h"
+#include "core/global.h"
+
 #include "module/http/request.h"
 #include "module/http/response.h"
 #include "module/http/session.h"
+#include "module/http/httpclient.h"
 #include "module/mysql.h"
+#include "module/mssql.h"
 #include "module/localstorage.h"
 #include "module/globalfuns.h"
-#include "core/define.h"
-#include "core/config.h"
-#include "core/global.h"
+#include "module/mutex.h"
+#include "module/codec.h"
+#include "module/time.h"
+
 #define LOOP_STATE_USE 1
 bool state_manager::start()
 {
@@ -35,7 +44,21 @@ void state_manager::close()
 sol::state* state_manager::create_state()
 {
 	sol::state* lua = new sol::state();
-	lua->open_libraries(sol::lib::base, sol::lib::package, sol::lib::math, sol::lib::string, sol::lib::table);
+	lua->open_libraries(
+		sol::lib::base, 
+		sol::lib::package, 
+		sol::lib::math, 
+		sol::lib::string,
+		sol::lib::table,
+		sol::lib::utf8,
+		sol::lib::bit32,
+		sol::lib::coroutine,
+		sol::lib::count,
+		sol::lib::ffi,
+		sol::lib::io,
+		sol::lib::jit,
+		sol::lib::os
+	);
 	{
 		// 获取当前的package.path,添加新的搜索路径
 		std::string current_path = (*lua)["package"]["path"];  // 获取当前的路径
@@ -45,9 +68,15 @@ sol::state* state_manager::create_state()
 	module::request::regist(*lua);
 	module::response::regist(*lua);
 	module::session::regist(*lua);
+	module::httpclient::regist(*lua);
 	module::mysql_regist(*lua);
+	module::mssql::regist(*lua);
 	module::regist_globalfuns(*lua);
 	module::local_storage::regist(lua);
+	module::mutex::regist(lua);
+	module::auto_lock::regist(lua);
+	module::codec::regist(lua);
+	module::time::regist(lua);
 
 	global::getInstance()->regist_lua(lua);
 	return lua;
@@ -106,3 +135,4 @@ bool state_manager::run()
 	return false;
 #endif
 }
+

+ 37 - 0
src/module/codec.cpp

@@ -0,0 +1,37 @@
+#include "codec.h"
+#include "util/codec.h"
+std::string module::codec::url_de(const std::string& value)
+{
+    return ylib::codec::url::de(value);
+}
+
+std::string module::codec::url_en(const std::string& value)
+{
+    return ylib::codec::url::en(value);
+}
+
+std::string module::codec::gbk_to_utf8(const std::string& value)
+{
+    return ylib::codec::to_utf8(value);
+}
+
+std::string module::codec::utf8_to_gbk(const std::string& value)
+{
+    return ylib::codec::to_gbk(value);
+}
+
+std::string module::codec::md5(const std::string& value)
+{
+    return ylib::codec::md5(value);
+}
+
+void module::codec::regist(sol::state* lua)
+{
+    lua->new_usertype<module::codec>("codec",
+        "url_de", &module::codec::url_de,
+        "url_en", &module::codec::url_en,
+        "gbk_to_utf8", &module::codec::gbk_to_utf8,
+        "utf8_to_gbk", &module::codec::utf8_to_gbk,
+        "md5", &module::codec::md5
+    );
+}

+ 37 - 0
src/module/codec.h

@@ -0,0 +1,37 @@
+#pragma once
+#include "sol/sol.hpp"
+#include "imodule.h"
+
+namespace module
+{
+	/// <summary>
+	/// 编解码
+	/// </summary>
+	class codec:public module::imodule {
+	public:
+		/// <summary>
+		/// URL解码
+		/// </summary>
+		static std::string url_de(const std::string& value);
+		/// <summary>
+		/// URL编码
+		/// </summary>
+		static std::string url_en(const std::string& value);
+		/// <summary>
+		/// GBK转UTF8
+		/// </summary>
+		/// <returns></returns>
+		static std::string gbk_to_utf8(const std::string& value);
+		static std::string utf8_to_gbk(const std::string& value);
+		/// <summary>
+		/// MD5校验
+		/// </summary>
+		/// <param name="value"></param>
+		/// <returns></returns>
+		static std::string md5(const std::string& value);
+
+		static void regist(sol::state* lua);
+	};
+
+}
+

+ 12 - 2
src/module/globalfuns.cpp

@@ -6,8 +6,8 @@
 static ylib::counter<uint64> s_counter_guid;
 void module::regist_globalfuns(sol::state& lua)
 {
-	//lua.set_function("global_get", module::global_get);
-	//lua.set_function("global_regist", module::global_regist);
+	lua.set_function("global_get", module::global_get);
+	lua.set_function("global_set", module::global_set);
 	lua.set_function("make_software_guid", module::make_software_guid);
 	lua.set_function("throw_string", module::throw_string);
 }
@@ -21,6 +21,16 @@ bool module::global_regist(const std::string& name, void* ptr, sol::this_state t
 	return global::getInstance()->regist_ptr(name,ptr, ts);
 }
 
+void module::global_set(const std::string& name, VarType value)
+{
+	global::getInstance()->set(name,value);
+}
+
+VarType module::global_get(const std::string& name, sol::this_state s)
+{
+	return global::getInstance()->get(name,s);
+}
+
 #if 0
 void* module::global_get(const std::string& name)
 {

+ 3 - 6
src/module/globalfuns.h

@@ -16,12 +16,9 @@ namespace module
 	/// </summary>
 	/// <returns></returns>
 	bool global_regist(const std::string& name, void* ptr, sol::this_state ts);
-	/// <summary>
-	/// 取全局指针(已废弃)
-	/// </summary>
-	/// <param name="name"></param>
-	/// <returns></returns>
-	void* global_get(const std::string& name) = delete;
+
+	void global_set(const std::string& name, VarType value);
+	VarType global_get(const std::string& name, sol::this_state s);
 	/// <summary>
 	/// 抛出异常
 	/// </summary>

+ 58 - 0
src/module/http/httpclient.cpp

@@ -0,0 +1,58 @@
+#include "httpclient.h"
+
+module::httpclient::httpclient()
+{
+}
+
+module::httpclient::~httpclient()
+{
+}
+
+void module::httpclient::set_timeout(uint32 connect_msec, uint32 recv_msec)
+{
+	m_client.set_timeout(connect_msec,recv_msec);
+}
+
+bool module::httpclient::get(const std::string& url)
+{
+	return m_client.get(url);
+}
+
+bool module::httpclient::post(const std::string& url, const std::string& body)
+{
+	return m_client.post(url,ylib::buffer(body));
+}
+
+void module::httpclient::request_header(const std::string& name, const std::string& value)
+{
+	m_client.headers_request().set(name, value);
+}
+
+std::string module::httpclient::response_header(const std::string& name)
+{
+	return m_client.headers_response().get(name).to_string();
+}
+
+std::string module::httpclient::response()
+{
+	return m_client.response().to_string();
+}
+
+ushort module::httpclient::status()
+{
+	return m_client.status();
+}
+
+void module::httpclient::regist(sol::state& state)
+{
+	state.new_usertype<module::httpclient>("httpclient",
+		"new", sol::constructors<module::httpclient()>(),
+		"get", &module::httpclient::get,
+		"post", &module::httpclient::post,
+		"set_timeout", &module::httpclient::set_timeout,
+		"request_header", &module::httpclient::request_header,
+		"response_header", &module::httpclient::response_header,
+		"status", &module::httpclient::status,
+		"response", &module::httpclient::response
+	);
+}

+ 25 - 0
src/module/http/httpclient.h

@@ -0,0 +1,25 @@
+#pragma once
+#include "sol/sol.hpp"
+#include "net/http_client_plus.h"
+namespace module
+{
+    class httpclient
+    {
+    public:
+        httpclient();
+        ~httpclient();
+
+        void set_timeout(uint32 connect_msec = 3000, uint32 recv_msec = 8000);
+        bool get(const std::string& url);
+        bool post(const std::string& url,const std::string& body);
+        void request_header(const std::string& name,const std::string& value);
+        std::string response_header(const std::string& name);
+        std::string response();
+        ushort status();
+
+        static void regist(sol::state& state);
+    private:
+        network::http::client_plus m_client;
+    };
+}
+

+ 29 - 28
src/module/http/request.cpp

@@ -19,6 +19,24 @@ module::session* module::request::session(const std::string& token)
         m_session = new module::session(&m_request->session(token));
     return m_session;
 }
+sol::table module::request::body_param(sol::this_state s)
+{
+    sol::state_view lua(s);
+    sol::table result_table = lua.create_table();
+    auto map = m_request->parser()->body_param();
+    for_iter(iter,map)
+        result_table[iter->first] = iter->second;
+    return result_table;
+}
+sol::table module::request::url_param(sol::this_state s)
+{
+    sol::state_view lua(s);
+    sol::table result_table = lua.create_table();
+    auto map = m_request->parser()->url_param();
+    for_iter(iter, map)
+        result_table[iter->first] = iter->second;
+    return result_table;
+}
 void* module::request::website()
 {
     return m_request->website();
@@ -33,11 +51,11 @@ void module::request::regist(sol::state& state)
         "host", &module::request::host,
         "remote_ipaddress", &module::request::remote_ipaddress,
         "remote_port", &module::request::remote_port,
-        "pstring", &module::request::pstring,
-        "pinteger", &module::request::pinteger,
-        "pnumber", &module::request::pnumber,
+        "param", &module::request::param,
         "session", &module::request::session,
-        "token", &module::request::token
+        "token", &module::request::token,
+        "body_param", &module::request::body_param,
+        "url_param", &module::request::url_param
     );
 }
 
@@ -60,35 +78,18 @@ std::string module::request::host()
 {
     return m_request->host();
 }
-std::string module::request::pstring(const std::string& name)
+VarType module::request::param(const std::string& name, bool throw_,sol::this_state s)
 {
     std::string value;
     bool result = request_param(name, value);
-    if (result == false) {
-        throw ylib::exception("request parameter '" + name + "' was not found");
+    if (result == false){
+        if (throw_)
+            throw ylib::exception("request parameter '" + name + "' was not found");
+        else
+            return sol::make_object(s, sol::nil);
     }
-    return value;
+    return sol::make_object(s,value);
 }
-int64 module::request::pinteger(const std::string& name)
-{
-    std::string value;
-    bool result = request_param(name, value);
-    if (result == false) {
-        throw ylib::exception("request parameter '" + name + "' was not found");
-    }
-    return ylib::stoll(value);
-}
-double module::request::pnumber(const std::string& name)
-{
-    std::string value;
-    bool result = request_param(name, value);
-    if (result == false) {
-        throw ylib::exception("request parameter '" + name + "' was not found");
-    }
-    return ylib::stod(value);
-}
-
-
 
 std::string module::request::remote_ipaddress(bool find_header, const std::string& inside_ipaddress)
 {

+ 5 - 3
src/module/http/request.h

@@ -3,6 +3,7 @@
 #include "net/http_response.h"
 
 #include "sol/sol.hpp"
+#include "core/define.h"
 namespace module
 {
     class session;
@@ -16,15 +17,16 @@ namespace module
         network::http::method method();
         std::string filepath();
         std::string host();
-        std::string pstring(const std::string& name);
-        int64 pinteger(const std::string& name);
-        double pnumber(const std::string& name);
+        VarType param(const std::string& name,bool throw_,sol::this_state s);
         std::string remote_ipaddress(bool find_header = false, const std::string& inside_ipaddress = "");
         ushort remote_port();
 
         std::string token();
         module::session* session(const std::string& token);
 
+        sol::table body_param(sol::this_state s);
+        sol::table url_param(sol::this_state s);
+
         void* website();
 
         static void regist(sol::state& state);

+ 1 - 0
src/module/imodule.h

@@ -1,6 +1,7 @@
 #pragma once
 #include "sol/sol.hpp"
 #include "core/define.h"
+
 namespace module
 {
 	/// <summary>

+ 0 - 3
src/module/localstorage.h

@@ -1,7 +1,4 @@
 #pragma once
-#include "db/mysql.h"
-#include "db/sqler.h"
-#include "sol/sol.hpp"
 #include "util/localstorage.h"
 #include "imodule.h"
 namespace module

+ 76 - 0
src/module/mssql.cpp

@@ -0,0 +1,76 @@
+#include "mssql.h"
+#include "soci/odbc/soci-odbc.h"
+module::mssql::mssql(const std::string& connstring)
+{
+    m_session = std::make_shared<soci::session>(soci::odbc, connstring);
+}
+
+module::mssql::~mssql()
+{
+    
+}
+std::string module::mssql::get_str(const std::string& name)
+{
+    if (m_iter == m_rows.end())
+        throw ylib::exception("no recorded data");
+    return m_iter->get<std::string>(name);
+}
+
+int32 module::mssql::get_i32(const std::string& name)
+{
+    if (m_iter == m_rows.end())
+        throw ylib::exception("no recorded data");
+    return m_iter->get<int32>(name);
+}
+
+int64 module::mssql::get_i64(const std::string& name)
+{
+    if (m_iter == m_rows.end())
+        throw ylib::exception("no recorded data");
+    return m_iter->get<int64>(name);
+}
+
+double module::mssql::get_dob(const std::string& name)
+{
+    if (m_iter == m_rows.end())
+        throw ylib::exception("no recorded data");
+    return m_iter->get<double>(name);
+}
+void module::mssql::query(const std::string& sql)
+{
+    m_read = false;
+    m_rows = (m_session->prepare << sql);
+    //m_iter = m_rows.begin();
+}
+uint64 module::mssql::update(const std::string& sql)
+{
+    soci::statement st = (m_session->prepare << sql);
+    return st.get_affected_rows();
+}
+bool module::mssql::next()
+{
+    if (m_read == false)
+    {
+        m_iter = m_rows.begin();
+        return true;
+    }
+    if (m_iter == m_rows.end())
+        return false;
+    m_iter++;
+    return true;
+}
+
+
+void module::mssql::regist(sol::state& lua)
+{
+    lua.new_usertype<module::mssql>("mssql",
+        "new", sol::constructors<module::mssql(const std::string&)>(),
+        "get_dob", &module::mssql::get_dob,
+        "get_i32", &module::mssql::get_i32,
+        "get_i64", &module::mssql::get_i64,
+        "get_str", &module::mssql::get_str,
+        "next", &module::mssql::next,
+        "query", &module::mssql::query,
+        "update", &module::mssql::update
+    );
+}

+ 54 - 0
src/module/mssql.h

@@ -0,0 +1,54 @@
+#pragma once
+#include "sol/sol.hpp"
+#include "imodule.h"
+#include "soci/soci.h"
+namespace module
+{
+	/// <summary>
+	/// 结果集
+	/// </summary>
+	class mssql
+	{
+	public:
+		mssql(const std::string& connstring);
+		~mssql();
+
+		/// <summary>
+		/// 取数据
+		/// </summary>
+		std::string get_str(const std::string& name);
+		int32 get_i32(const std::string& name);
+		int64 get_i64(const std::string& name);
+		double get_dob(const std::string& name);
+		void query(const std::string& sql);
+		/*/// <summary>
+		/// 绑定
+		/// </summary>
+		/// <param name="value"></param>
+		void bind_str(const std::string& value);
+		void bind_i32(int32 value);
+		void bind_i64(int64 value);
+		void bind_dob(double value);*/
+		/// <summary>
+		/// 下一行
+		/// </summary>
+		bool next();
+
+
+		uint64 update(const std::string& sql);
+		/// <summary>
+		/// 注册
+		/// </summary>
+		/// <param name="lua"></param>
+		static void regist(sol::state& lua);
+	private:
+		std::shared_ptr<soci::session> m_session;
+		//std::shared_ptr<soci::statement> m_st;
+		soci::rowset_iterator<soci::row> m_iter;
+		soci::rowset<soci::row> m_rows;
+		bool m_read = false;
+	};
+
+
+}
+

+ 58 - 0
src/module/mutex.cpp

@@ -0,0 +1,58 @@
+#include "mutex.h"
+
+module::mutex::mutex()
+{
+}
+
+module::mutex::~mutex()
+{
+}
+
+void module::mutex::lock()
+{
+    m_mutex.lock();
+}
+
+void module::mutex::unlock()
+{
+    m_mutex.unlock();
+}
+
+bool module::mutex::try_lock()
+{
+    return m_mutex.try_lock();
+}
+
+void module::mutex::regist(sol::state* lua)
+{
+    lua->new_usertype<module::mutex>("mutex",
+        "new", sol::constructors<module::mutex()>(),
+        "lock", &module::mutex::lock,
+        "unlock", &module::mutex::unlock,
+        "try_lock", &module::mutex::try_lock,
+        "self", &module::mutex::self
+    );
+}
+
+void module::mutex::regist_global(const std::string& name, sol::state* lua)
+{
+    lua->registry()[name] = this;
+    (*lua)[name] = this;
+}
+
+module::auto_lock::auto_lock(module::mutex& mutex):m_mutex(&mutex)
+{
+    m_mutex->lock();
+}
+
+module::auto_lock::~auto_lock()
+{
+    m_mutex->unlock();
+}
+
+void module::auto_lock::regist(sol::state* lua)
+{
+    lua->new_usertype<module::auto_lock>("auto_lock",
+        "new", sol::constructors<module::auto_lock(module::mutex&)>()
+    );
+}

+ 47 - 0
src/module/mutex.h

@@ -0,0 +1,47 @@
+#pragma once
+#include "sol/sol.hpp"
+#include "imodule.h"
+
+namespace module
+{
+	/// <summary>
+	/// 互斥锁
+	/// </summary>
+	class mutex:public module::imodule {
+	public:
+		mutex();
+		~mutex();
+		/// <summary>
+		/// 加锁
+		/// </summary>
+		void lock();
+		/// <summary>
+		/// 释放锁
+		/// </summary>
+		void unlock();
+		/// <summary>
+		/// 尝试加锁
+		/// </summary>
+		/// <returns></returns>
+		bool try_lock();
+		static void regist(sol::state* lua);
+	private:
+		// 通过 imodule 继承
+		virtual void regist_global(const std::string& name, sol::state* lua);
+		std::mutex m_mutex;
+	};
+
+	/// <summary>
+	/// 自动锁
+	/// </summary>
+	class auto_lock 
+	{
+	public:
+		auto_lock(module::mutex& mutex);
+		~auto_lock();
+		static void regist(sol::state* lua);
+	private:
+		module::mutex *m_mutex = nullptr;
+	};
+}
+

+ 39 - 13
src/module/mysql.cpp

@@ -45,9 +45,17 @@ module::select& module::select::table(const std::string& table_name)
     return *this;
 }
 
-module::select& module::select::field(const std::vector<std::string>& field)
+module::select& module::select::field(sol::table table)
 {
-    m_select->field(field);
+    std::vector<std::string> strings;
+    for (auto& pair : table) {
+        if (pair.second.get_type() != sol::type::string)
+        {
+            throw ylib::exception("module::select::field:  attempting to obtain field name that is not a string");
+        }
+        strings.push_back(pair.second.as<std::string>());
+    }
+    m_select->field(strings);
     return *this;
 }
 
@@ -409,7 +417,6 @@ void module::mysql_regist(sol::state& lua)
 
 module::mysql::mysql()
 {
-    std::cout << this << std::endl;
 }
 
 module::mysql::~mysql()
@@ -502,19 +509,39 @@ bool module::mysql_result::next()
     return m_result->next();
 }
 
-VarType module::mysql_result::get(const std::string& name)
+VarType module::mysql_result::get(sol::object obj, sol::this_state s)
 {
-    auto type = m_result->field_type(name);
+    std::string type;
+    if (obj.get_type() == sol::type::string)
+        type = m_result->field_type(obj.as<std::string>());
+    else if (obj.get_type() == sol::type::number)
+        type = m_result->field_type(obj.as<int>());
+
+#define GET_VALUE(FUNCTION)                                                                                             \
+    if (obj.get_type() == sol::type::string)                                                                                    \
+        return sol::make_object(s, m_result->FUNCTION(obj.as<std::string>()));                          \
+    else if (obj.get_type() == sol::type::number)                                                                           \
+        return sol::make_object(s, m_result->FUNCTION(obj.as<uint32>()))
+
     if (type == "int" || type == "tinyint")
-        return m_result->get_int32(name);
+    {
+        GET_VALUE(get_int32);
+    }
+      
     else if (type == "varchar")
-        return m_result->get_string(name);
+    {
+        GET_VALUE(get_string);
+    }
     else if (type == "int unsigned")
-        return m_result->get_uint32(name);
+    {
+        GET_VALUE(get_uint32);
+    }
     else if (type == "bigint")
-        return m_result->get_int64(name);
-    else
-        return std::monostate();
+    {
+        GET_VALUE(get_int64);
+    }
+    return sol::make_object(s, sol::nil);
+    
 }
 
 sol::table module::mysql_result::table(sol::this_state s)
@@ -526,8 +553,7 @@ sol::table module::mysql_result::table(sol::this_state s)
     while (next()) {
         sol::table row = lua.create_table();
         for (uint32_t i = 0; i < field_count(); ++i) {
-            std::string field = field_name(i+1);
-            row[field] = get(field);
+            row[field_name(i+1)] = get(sol::make_object(s, i+1), s);
         }
         result_table[row_num++] = row;
     }

+ 2 - 2
src/module/mysql.h

@@ -50,7 +50,7 @@ namespace module
 		/// </summary>
 		/// <param name="name"></param>
 		/// <returns></returns>
-		VarType get(const std::string& name);
+		VarType get(sol::object obj, sol::this_state s);
 		/// <summary>
 		/// 取结果集到table
 		/// </summary>
@@ -77,7 +77,7 @@ namespace module
 		module::select& where_str(const std::string& name, const std::string& expression, const std::string& value);
 		module::select& where_expression(const std::string& expression);
 		module::select& table(const std::string& table_name);
-		module::select& field(const std::vector<std::string>& field);
+		module::select& field(sol::table table);
 		module::select& page(uint32 page, uint32 count);
 		module::select& limit(uint32 start, uint32 count);
 		module::select& orderby(const std::string& field, int sort);

Неке датотеке нису приказане због велике количине промена