From 764424040a0b5c0380432055fc4277059f7695a3 Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Tue, 5 Apr 2022 23:38:51 +0200 Subject: [PATCH 01/46] Update core code for complete integer type support --- include/private/soci-exchange-cast.h | 41 +++++++-- include/private/soci-vector-helpers.h | 64 ++++++++++----- include/soci/column-info.h | 33 ++++++-- include/soci/exchange-traits.h | 76 ++++++++++++----- include/soci/soci-backend.h | 40 ++++++--- include/soci/soci.h | 1 - include/soci/unsigned-types.h | 114 -------------------------- src/core/statement.cpp | 70 +++++++++++++--- src/core/use-type.cpp | 32 ++++++-- 9 files changed, 269 insertions(+), 202 deletions(-) delete mode 100644 include/soci/unsigned-types.h diff --git a/include/private/soci-exchange-cast.h b/include/private/soci-exchange-cast.h index 9f5b6cfdd..147a395f9 100644 --- a/include/private/soci-exchange-cast.h +++ b/include/private/soci-exchange-cast.h @@ -12,6 +12,7 @@ #include "soci/type-wrappers.h" #include +#include namespace soci { @@ -35,27 +36,51 @@ struct exchange_type_traits }; template <> -struct exchange_type_traits +struct exchange_type_traits { - typedef short value_type; + typedef int8_t value_type; }; template <> -struct exchange_type_traits +struct exchange_type_traits { - typedef int value_type; + typedef uint8_t value_type; }; template <> -struct exchange_type_traits +struct exchange_type_traits { - typedef long long value_type; + typedef int16_t value_type; }; template <> -struct exchange_type_traits +struct exchange_type_traits { - typedef unsigned long long value_type; + typedef uint16_t value_type; +}; + +template <> +struct exchange_type_traits +{ + typedef int32_t value_type; +}; + +template <> +struct exchange_type_traits +{ + typedef uint32_t value_type; +}; + +template <> +struct exchange_type_traits +{ + typedef int64_t value_type; +}; + +template <> +struct exchange_type_traits +{ + typedef uint64_t value_type; }; template <> diff --git a/include/private/soci-vector-helpers.h b/include/private/soci-vector-helpers.h index eae5fbabd..d4eff1443 100644 --- a/include/private/soci-vector-helpers.h +++ b/include/private/soci-vector-helpers.h @@ -33,14 +33,22 @@ inline std::size_t get_vector_size(exchange_type e, void *data) return exchange_vector_type_cast(data).size(); case x_stdstring: return exchange_vector_type_cast(data).size(); - case x_short: - return exchange_vector_type_cast(data).size(); - case x_integer: - return exchange_vector_type_cast(data).size(); - case x_long_long: - return exchange_vector_type_cast(data).size(); - case x_unsigned_long_long: - return exchange_vector_type_cast(data).size(); + case x_int8: + return exchange_vector_type_cast(data).size(); + case x_uint8: + return exchange_vector_type_cast(data).size(); + case x_int16: + return exchange_vector_type_cast(data).size(); + case x_uint16: + return exchange_vector_type_cast(data).size(); + case x_int32: + return exchange_vector_type_cast(data).size(); + case x_uint32: + return exchange_vector_type_cast(data).size(); + case x_int64: + return exchange_vector_type_cast(data).size(); + case x_uint64: + return exchange_vector_type_cast(data).size(); case x_double: return exchange_vector_type_cast(data).size(); case x_stdtm: @@ -68,17 +76,29 @@ inline void resize_vector(exchange_type e, void *data, std::size_t newSize) case x_stdstring: exchange_vector_type_cast(data).resize(newSize); return; - case x_short: - exchange_vector_type_cast(data).resize(newSize); + case x_int8: + exchange_vector_type_cast(data).resize(newSize); return; - case x_integer: - exchange_vector_type_cast(data).resize(newSize); + case x_uint8: + exchange_vector_type_cast(data).resize(newSize); return; - case x_long_long: - exchange_vector_type_cast(data).resize(newSize); + case x_int16: + exchange_vector_type_cast(data).resize(newSize); return; - case x_unsigned_long_long: - exchange_vector_type_cast(data).resize(newSize); + case x_uint16: + exchange_vector_type_cast(data).resize(newSize); + return; + case x_int32: + exchange_vector_type_cast(data).resize(newSize); + return; + case x_uint32: + exchange_vector_type_cast(data).resize(newSize); + return; + case x_int64: + exchange_vector_type_cast(data).resize(newSize); + return; + case x_uint64: + exchange_vector_type_cast(data).resize(newSize); return; case x_double: exchange_vector_type_cast(data).resize(newSize); @@ -112,10 +132,14 @@ inline std::string& vector_string_value(exchange_type e, void *data, std::size_t case x_longstring: return exchange_vector_type_cast(data).at(ind).value; case x_char: - case x_short: - case x_integer: - case x_long_long: - case x_unsigned_long_long: + 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: diff --git a/include/soci/column-info.h b/include/soci/column-info.h index 2105628e7..bc7f683a9 100644 --- a/include/soci/column-info.h +++ b/include/soci/column-info.h @@ -12,6 +12,8 @@ #include "soci/type-conversion.h" #include "soci/values.h" +#include + namespace soci { @@ -39,15 +41,30 @@ struct type_conversion case dt_double: return static_cast( v.get(field_name, 0.0)); - case dt_integer: + case dt_int8: + return static_cast( + v.get(field_name, 0)); + case dt_uint8: + return static_cast( + v.get(field_name, 0)); + case dt_int16: + return static_cast( + v.get(field_name, 0)); + case dt_uint16: + return static_cast( + v.get(field_name, 0)); + case dt_int32: + return static_cast( + v.get(field_name, 0)); + case dt_uint32: return static_cast( - v.get(field_name, 0)); - case dt_long_long: + v.get(field_name, 0)); + case dt_int64: return static_cast( - v.get(field_name, 0ll)); - case dt_unsigned_long_long: + v.get(field_name, 0ll)); + case dt_uint64: return static_cast( - v.get(field_name, 0ull)); + v.get(field_name, 0ull)); break; default: return 0u; @@ -72,7 +89,7 @@ struct type_conversion } else if (type_name == "integer" || type_name == "INTEGER") { - ci.type = dt_integer; + ci.type = dt_int32; } else if (type_name.find("number") != std::string::npos || type_name.find("NUMBER") != std::string::npos || @@ -85,7 +102,7 @@ struct type_conversion } else { - ci.type = dt_integer; + ci.type = dt_int32; } } else if (type_name.find("time") != std::string::npos || diff --git a/include/soci/exchange-traits.h b/include/soci/exchange-traits.h index 77f558698..971ba5a8b 100644 --- a/include/soci/exchange-traits.h +++ b/include/soci/exchange-traits.h @@ -13,6 +13,7 @@ #include "soci/type-wrappers.h" // std #include +#include #include #include @@ -43,66 +44,94 @@ struct exchange_traits }; template <> -struct exchange_traits +struct exchange_traits { typedef basic_type_tag type_family; - enum { x_type = x_short }; + enum { x_type = x_int8 }; }; template <> -struct exchange_traits : exchange_traits +struct exchange_traits { + typedef basic_type_tag type_family; + enum { x_type = x_uint8 }; }; template <> -struct exchange_traits +struct exchange_traits { typedef basic_type_tag type_family; - enum { x_type = x_integer }; + enum { x_type = x_int16 }; }; template <> -struct exchange_traits : exchange_traits +struct exchange_traits { + typedef basic_type_tag type_family; + enum { x_type = x_uint16 }; }; template <> -struct exchange_traits +struct exchange_traits { typedef basic_type_tag type_family; - enum { x_type = x_char }; + enum { x_type = x_int32 }; }; template <> -struct exchange_traits +struct exchange_traits { typedef basic_type_tag type_family; - enum { x_type = x_long_long }; + enum { x_type = x_uint32 }; }; template <> -struct exchange_traits +struct exchange_traits { typedef basic_type_tag type_family; - enum { x_type = x_unsigned_long_long }; + enum { x_type = x_int64 }; }; -// long must be mapped either to x_integer or x_long_long: -template struct long_traits_helper; -template<> struct long_traits_helper<4> { enum { x_type = x_integer }; }; -template<> struct long_traits_helper<8> { enum { x_type = x_long_long }; }; - template <> -struct exchange_traits +struct exchange_traits { typedef basic_type_tag type_family; - enum { x_type = long_traits_helper::x_type }; + enum { x_type = x_uint64 }; +}; + +#if defined(_WIN64) +template <> +struct exchange_traits : exchange_traits +{ +}; + +template <> +struct exchange_traits : exchange_traits +{ +}; +#elif defined(__APPLE__) +template <> +struct exchange_traits : exchange_traits +{ +}; + +template <> +struct exchange_traits : exchange_traits +{ +}; +#elif defined(__LP64__) || (__WORDSIZE == 64) +template <> +struct exchange_traits : exchange_traits +{ }; template <> -struct exchange_traits : exchange_traits +struct exchange_traits : exchange_traits { }; +#else +#error "Unhandled type architecture" +#endif template <> struct exchange_traits @@ -111,6 +140,13 @@ struct exchange_traits enum { x_type = x_double }; }; +template <> +struct exchange_traits +{ + typedef basic_type_tag type_family; + enum { x_type = x_char }; +}; + template <> struct exchange_traits { diff --git a/include/soci/soci-backend.h b/include/soci/soci-backend.h index 237f6587a..ccd0b7a8a 100644 --- a/include/soci/soci-backend.h +++ b/include/soci/soci-backend.h @@ -22,8 +22,19 @@ namespace soci // data types, as seen by the user enum data_type { - dt_string, dt_date, dt_double, dt_integer, dt_long_long, dt_unsigned_long_long, - dt_blob, dt_xml + dt_string, + dt_int8, + dt_uint8, + dt_int16, + dt_uint16, + dt_int32, + dt_uint32, + dt_int64, + dt_uint64, + dt_double, + dt_date, + dt_blob, + dt_xml }; // the enum type for indicator variables @@ -40,10 +51,14 @@ enum exchange_type { x_char, x_stdstring, - x_short, - x_integer, - x_long_long, - x_unsigned_long_long, + x_int8, + x_uint8, + x_int16, + x_uint16, + x_int32, + x_uint32, + x_int64, + x_uint64, x_double, x_stdtm, x_statement, @@ -358,15 +373,18 @@ class session_backend } break; - case dt_integer: - res += "integer"; + case dt_int16: + case dt_uint16: + res += "smallint"; break; - case dt_long_long: - res += "bigint"; + case dt_int32: + case dt_uint32: + res += "integer"; break; - case dt_unsigned_long_long: + case dt_int64: + case dt_uint64: res += "bigint"; break; diff --git a/include/soci/soci.h b/include/soci/soci.h index 628cd6e7e..291878366 100644 --- a/include/soci/soci.h +++ b/include/soci/soci.h @@ -38,7 +38,6 @@ #include "soci/type-holder.h" #include "soci/type-ptr.h" #include "soci/type-wrappers.h" -#include "soci/unsigned-types.h" #include "soci/use.h" #include "soci/use-type.h" #include "soci/values.h" diff --git a/include/soci/unsigned-types.h b/include/soci/unsigned-types.h deleted file mode 100644 index 0d496a462..000000000 --- a/include/soci/unsigned-types.h +++ /dev/null @@ -1,114 +0,0 @@ -// -// Copyright (C) 2010 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_UNSIGNED_TYPES_H_INCLUDED -#define SOCI_UNSIGNED_TYPES_H_INCLUDED - -#include "soci/type-conversion-traits.h" -#include - -namespace soci -{ - -// simple fall-back for unsigned types - -template <> -struct type_conversion -{ - typedef long long base_type; - - static void from_base(base_type const & in, indicator ind, - unsigned char & out) - { - if (ind == i_null) - { - throw soci_error("Null value not allowed for this type."); - } - - const base_type max = (std::numeric_limits::max)(); - const base_type min = (std::numeric_limits::min)(); - if (in < min || in > max) - { - throw soci_error("Value outside of allowed range."); - } - - out = static_cast(in); - } - - static void to_base(unsigned char const & in, - base_type & out, indicator & ind) - { - out = static_cast(in); - ind = i_ok; - } -}; - -template <> -struct type_conversion -{ - typedef long long base_type; - - static void from_base(base_type const & in, indicator ind, - unsigned short & out) - { - if (ind == i_null) - { - throw soci_error("Null value not allowed for this type."); - } - - const long long max = (std::numeric_limits::max)(); - const long long min = (std::numeric_limits::min)(); - if (in < min || in > max) - { - throw soci_error("Value outside of allowed range."); - } - - out = static_cast(in); - } - - static void to_base(unsigned short const & in, - base_type & out, indicator & ind) - { - out = static_cast(in); - ind = i_ok; - } -}; - -template <> -struct type_conversion -{ - typedef long long base_type; - - static void from_base(base_type const & in, indicator ind, - unsigned int & out) - { - if (ind == i_null) - { - throw soci_error("Null value not allowed for this type."); - } - - const long long max = (std::numeric_limits::max)(); - const long long min = (std::numeric_limits::min)(); - if (in < min || in > max) - { - throw soci_error("Value outside of allowed range."); - } - - out = static_cast(in); - } - - static void to_base(unsigned int const & in, - base_type & out, indicator & ind) - { - out = static_cast(in); - ind = i_ok; - } -}; - -} // namespace soci - -#endif // SOCI_UNSIGNED_TYPES_H_INCLUDED diff --git a/src/core/statement.cpp b/src/core/statement.cpp index 4bf9f0e79..8f3d0a953 100644 --- a/src/core/statement.cpp +++ b/src/core/statement.cpp @@ -14,6 +14,7 @@ #include "soci-compiler.h" #include #include +#include using namespace soci; using namespace soci::details; @@ -641,21 +642,51 @@ void statement_impl::bind_into() } template<> -void statement_impl::bind_into() +void statement_impl::bind_into() { - into_row(); + into_row(); } template<> -void statement_impl::bind_into() +void statement_impl::bind_into() { - into_row(); + into_row(); } template<> -void statement_impl::bind_into() +void statement_impl::bind_into() { - into_row(); + into_row(); +} + +template<> +void statement_impl::bind_into() +{ + into_row(); +} + +template<> +void statement_impl::bind_into() +{ + into_row(); +} + +template<> +void statement_impl::bind_into() +{ + into_row(); +} + +template<> +void statement_impl::bind_into() +{ + into_row(); +} + +template<> +void statement_impl::bind_into() +{ + into_row(); } template<> @@ -694,14 +725,29 @@ void statement_impl::describe() case dt_double: bind_into(); break; - case dt_integer: - bind_into(); + case dt_int8: + bind_into(); + break; + case dt_uint8: + bind_into(); + break; + case dt_int16: + bind_into(); + break; + case dt_uint16: + bind_into(); + break; + case dt_int32: + bind_into(); + break; + case dt_uint32: + bind_into(); break; - case dt_long_long: - bind_into(); + case dt_int64: + bind_into(); break; - case dt_unsigned_long_long: - bind_into(); + case dt_uint64: + bind_into(); break; case dt_date: bind_into(); diff --git a/src/core/use-type.cpp b/src/core/use-type.cpp index b865f74f4..26d165dc5 100644 --- a/src/core/use-type.cpp +++ b/src/core/use-type.cpp @@ -57,20 +57,36 @@ void standard_use_type::dump_value(std::ostream& os) const os << "\"" << exchange_type_cast(data_) << "\""; return; - case x_short: - os << exchange_type_cast(data_); + case x_int8: + os << exchange_type_cast(data_); return; - case x_integer: - os << exchange_type_cast(data_); + case x_uint8: + os << exchange_type_cast(data_); return; - case x_long_long: - os << exchange_type_cast(data_); + case x_int16: + os << exchange_type_cast(data_); return; - case x_unsigned_long_long: - os << exchange_type_cast(data_); + case x_uint16: + os << exchange_type_cast(data_); + return; + + case x_int32: + os << exchange_type_cast(data_); + return; + + case x_uint32: + os << exchange_type_cast(data_); + return; + + case x_int64: + os << exchange_type_cast(data_); + return; + + case x_uint64: + os << exchange_type_cast(data_); return; case x_double: From 53f6aba389505823ccf9c286c3d9602569218507 Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Tue, 5 Apr 2022 23:11:19 +0200 Subject: [PATCH 02/46] Update MySQL backend for complete integer type support --- src/backends/mysql/standard-into-type.cpp | 37 +++++-- src/backends/mysql/standard-use-type.cpp | 63 +++++++++--- src/backends/mysql/statement.cpp | 17 +++- src/backends/mysql/vector-into-type.cpp | 75 ++++++++++---- src/backends/mysql/vector-use-type.cpp | 119 ++++++++++++++++------ 5 files changed, 236 insertions(+), 75 deletions(-) diff --git a/src/backends/mysql/standard-into-type.cpp b/src/backends/mysql/standard-into-type.cpp index 06dfc47cc..15528bc1f 100644 --- a/src/backends/mysql/standard-into-type.cpp +++ b/src/backends/mysql/standard-into-type.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #ifdef _MSC_VER @@ -89,17 +90,37 @@ void mysql_standard_into_type_backend::post_fetch( dest.assign(buf, lengths[pos]); } break; - case x_short: - parse_num(buf, exchange_type_cast(data_)); + case x_int8: + { + int32_t tmp = 0; + parse_num(buf, tmp); + exchange_type_cast(data_) = static_cast(tmp); + } + break; + case x_uint8: + { + uint32_t tmp = 0; + parse_num(buf, tmp); + exchange_type_cast(data_) = static_cast(tmp); + } + break; + case x_int16: + parse_num(buf, exchange_type_cast(data_)); + break; + case x_uint16: + parse_num(buf, exchange_type_cast(data_)); + break; + case x_int32: + parse_num(buf, exchange_type_cast(data_)); break; - case x_integer: - parse_num(buf, exchange_type_cast(data_)); + case x_uint32: + parse_num(buf, exchange_type_cast(data_)); break; - case x_long_long: - parse_num(buf, exchange_type_cast(data_)); + case x_int64: + parse_num(buf, exchange_type_cast(data_)); break; - case x_unsigned_long_long: - parse_num(buf, exchange_type_cast(data_)); + case x_uint64: + parse_num(buf, exchange_type_cast(data_)); break; case x_double: parse_num(buf, exchange_type_cast(data_)); diff --git a/src/backends/mysql/standard-use-type.cpp b/src/backends/mysql/standard-use-type.cpp index 362958e2f..e88633e67 100644 --- a/src/backends/mysql/standard-use-type.cpp +++ b/src/backends/mysql/standard-use-type.cpp @@ -17,6 +17,7 @@ #include #include #include +#include using namespace soci; using namespace soci::details; @@ -64,38 +65,76 @@ void mysql_standard_use_type_backend::pre_use(indicator const *ind) s.c_str(), s.size()); } break; - case x_short: + case x_int8: { std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; snprintf(buf_, bufSize, "%d", - static_cast(exchange_type_cast(data_))); + static_cast(exchange_type_cast(data_))); } break; - case x_integer: + case x_uint8: { std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; - snprintf(buf_, bufSize, "%d", exchange_type_cast(data_)); + snprintf(buf_, bufSize, "%u", + static_cast(exchange_type_cast(data_))); } break; - case x_long_long: + case x_int16: { std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; - snprintf(buf_, bufSize, "%" LL_FMT_FLAGS "d", exchange_type_cast(data_)); + snprintf(buf_, bufSize, "%d", + static_cast(exchange_type_cast(data_))); + } + break; + case x_uint16: + { + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf_ = new char[bufSize]; + snprintf(buf_, bufSize, "%u", + static_cast(exchange_type_cast(data_))); + } + break; + case x_int32: + { + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf_ = new char[bufSize]; + snprintf(buf_, bufSize, "%d", + static_cast(exchange_type_cast(data_))); + } + break; + case x_uint32: + { + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf_ = new char[bufSize]; + snprintf(buf_, bufSize, "%u", + static_cast(exchange_type_cast(data_))); + } + break; + case x_int64: + { + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf_ = new char[bufSize]; + snprintf(buf_, bufSize, "%" LL_FMT_FLAGS "d", + static_cast(exchange_type_cast(data_))); } break; - case x_unsigned_long_long: + case x_uint64: { std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; snprintf(buf_, bufSize, "%" LL_FMT_FLAGS "u", - exchange_type_cast(data_)); + static_cast(exchange_type_cast(data_))); } break; diff --git a/src/backends/mysql/statement.cpp b/src/backends/mysql/statement.cpp index cfa91a16e..3d83201b3 100644 --- a/src/backends/mysql/statement.cpp +++ b/src/backends/mysql/statement.cpp @@ -409,17 +409,24 @@ void mysql_statement_backend::describe_column(int colNum, switch (field->type) { case FIELD_TYPE_CHAR: //MYSQL_TYPE_TINY: + type = field->flags & UNSIGNED_FLAG ? dt_uint8 : + dt_int8; + break; case FIELD_TYPE_SHORT: //MYSQL_TYPE_SHORT: + type = field->flags & UNSIGNED_FLAG ? dt_uint16 : + dt_int16; + break; case FIELD_TYPE_INT24: //MYSQL_TYPE_INT24: - type = dt_integer; + type = field->flags & UNSIGNED_FLAG ? dt_uint32 + : dt_int32; break; case FIELD_TYPE_LONG: //MYSQL_TYPE_LONG: - type = field->flags & UNSIGNED_FLAG ? dt_long_long - : dt_integer; + type = field->flags & UNSIGNED_FLAG ? dt_uint32 + : dt_int32; break; case FIELD_TYPE_LONGLONG: //MYSQL_TYPE_LONGLONG: - type = field->flags & UNSIGNED_FLAG ? dt_unsigned_long_long : - dt_long_long; + type = field->flags & UNSIGNED_FLAG ? dt_uint64 : + dt_int64; break; case FIELD_TYPE_FLOAT: //MYSQL_TYPE_FLOAT: case FIELD_TYPE_DOUBLE: //MYSQL_TYPE_DOUBLE: diff --git a/src/backends/mysql/vector-into-type.cpp b/src/backends/mysql/vector-into-type.cpp index 9cc6da633..f9de6b654 100644 --- a/src/backends/mysql/vector-into-type.cpp +++ b/src/backends/mysql/vector-into-type.cpp @@ -13,6 +13,7 @@ #include "soci/soci-platform.h" #include #include +#include using namespace soci; using namespace soci::details; @@ -108,30 +109,60 @@ void mysql_vector_into_type_backend::post_fetch(bool gotData, indicator *ind) (*dest)[i].assign(buf, lengths[pos]); } break; - case x_short: + case x_int8: { - short val; + int32_t tmp = 0; + parse_num(buf, tmp); + int8_t val = static_cast(tmp); + set_invector_(data_, i, val); + } + break; + case x_uint8: + { + uint32_t tmp = 0; + parse_num(buf, tmp); + uint8_t val = static_cast(tmp); + set_invector_(data_, i, val); + } + break; + case x_int16: + { + int16_t val; + parse_num(buf, val); + set_invector_(data_, i, val); + } + break; + case x_uint16: + { + uint16_t val; + parse_num(buf, val); + set_invector_(data_, i, val); + } + break; + case x_int32: + { + int32_t val; parse_num(buf, val); set_invector_(data_, i, val); } break; - case x_integer: + case x_uint32: { - int val; + uint32_t val; parse_num(buf, val); set_invector_(data_, i, val); } break; - case x_long_long: + case x_int64: { - long long val; + int64_t val; parse_num(buf, val); set_invector_(data_, i, val); } break; - case x_unsigned_long_long: + case x_uint64: { - unsigned long long val; + uint64_t val; parse_num(buf, val); set_invector_(data_, i, val); } @@ -182,12 +213,14 @@ void mysql_vector_into_type_backend::resize(std::size_t sz) { // simple cases case x_char: resizevector_ (data_, sz); break; - case x_short: resizevector_ (data_, sz); break; - case x_integer: resizevector_ (data_, sz); break; - case x_long_long: resizevector_ (data_, sz); break; - case x_unsigned_long_long: - resizevector_(data_, sz); - break; + case x_int8: resizevector_ (data_, sz); break; + case x_uint8: resizevector_ (data_, sz); break; + case x_int16: resizevector_ (data_, sz); break; + case x_uint16: resizevector_ (data_, sz); break; + case x_int32: resizevector_ (data_, sz); break; + case x_uint32: resizevector_ (data_, sz); break; + case x_int64: resizevector_ (data_, sz); break; + case x_uint64: resizevector_ (data_, sz); break; case x_double: resizevector_ (data_, sz); break; case x_stdstring: resizevector_ (data_, sz); break; case x_stdtm: resizevector_ (data_, sz); break; @@ -204,12 +237,14 @@ std::size_t mysql_vector_into_type_backend::size() { // simple cases case x_char: sz = get_vector_size (data_); break; - case x_short: sz = get_vector_size (data_); break; - case x_integer: sz = get_vector_size (data_); break; - case x_long_long: sz = get_vector_size (data_); break; - case x_unsigned_long_long: - sz = get_vector_size(data_); - break; + case x_int8: sz = get_vector_size (data_); break; + case x_uint8: sz = get_vector_size (data_); break; + case x_int16: sz = get_vector_size (data_); break; + case x_uint16: sz = get_vector_size (data_); break; + case x_int32: sz = get_vector_size (data_); break; + case x_uint32: sz = get_vector_size (data_); break; + case x_int64: sz = get_vector_size (data_); break; + case x_uint64: sz = get_vector_size (data_); break; case x_double: sz = get_vector_size (data_); break; case x_stdstring: sz = get_vector_size (data_); break; case x_stdtm: sz = get_vector_size (data_); break; diff --git a/src/backends/mysql/vector-use-type.cpp b/src/backends/mysql/vector-use-type.cpp index 67a5e1906..25a283001 100644 --- a/src/backends/mysql/vector-use-type.cpp +++ b/src/backends/mysql/vector-use-type.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -81,52 +82,108 @@ void mysql_vector_use_type_backend::pre_use(indicator const *ind) v[i].c_str(), v[i].size()); } break; - case x_short: + case x_int8: { - std::vector *pv - = static_cast *>(data_); - std::vector &v = *pv; + std::vector *pv + = static_cast *>(data_); + std::vector &v = *pv; std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%d", static_cast(v[i])); + snprintf(buf, bufSize, "%d", + static_cast(v[i])); } break; - case x_integer: + case x_uint8: { - std::vector *pv - = static_cast *>(data_); - std::vector &v = *pv; + std::vector *pv + = static_cast *>(data_); + std::vector &v = *pv; std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%d", v[i]); + snprintf(buf, bufSize, "%u", + static_cast(v[i])); } break; - case x_long_long: + case x_int16: { - std::vector *pv - = static_cast *>(data_); - std::vector &v = *pv; + std::vector *pv + = static_cast *>(data_); + std::vector &v = *pv; std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%" LL_FMT_FLAGS "d", v[i]); + snprintf(buf, bufSize, "%d", + static_cast(v[i])); } break; - case x_unsigned_long_long: + case x_uint16: { - std::vector *pv - = static_cast *>(data_); - std::vector &v = *pv; + std::vector *pv + = static_cast *>(data_); + std::vector &v = *pv; std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%" LL_FMT_FLAGS "u", v[i]); + snprintf(buf, bufSize, "%u", + static_cast(v[i])); + } + break; + case x_int32: + { + std::vector *pv + = static_cast *>(data_); + std::vector &v = *pv; + + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf = new char[bufSize]; + snprintf(buf, bufSize, "%d", + static_cast(v[i])); + } + break; + case x_uint32: + { + std::vector *pv + = static_cast *>(data_); + std::vector &v = *pv; + + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf = new char[bufSize]; + snprintf(buf, bufSize, "%u", + static_cast(v[i])); + } + break; + case x_int64: + { + std::vector *pv + = static_cast *>(data_); + std::vector &v = *pv; + + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf = new char[bufSize]; + snprintf(buf, bufSize, "%" LL_FMT_FLAGS "d", + static_cast(v[i])); + } + break; + case x_uint64: + { + std::vector *pv + = static_cast *>(data_); + std::vector &v = *pv; + + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf = new char[bufSize]; + snprintf(buf, bufSize, "%" LL_FMT_FLAGS "u", + static_cast(v[i])); } break; case x_double: @@ -190,12 +247,14 @@ std::size_t mysql_vector_use_type_backend::size() { // simple cases case x_char: sz = get_vector_size (data_); break; - case x_short: sz = get_vector_size (data_); break; - case x_integer: sz = get_vector_size (data_); break; - case x_long_long: sz = get_vector_size (data_); break; - case x_unsigned_long_long: - sz = get_vector_size(data_); - break; + case x_int8: sz = get_vector_size (data_); break; + case x_uint8: sz = get_vector_size (data_); break; + case x_int16: sz = get_vector_size (data_); break; + case x_uint16: sz = get_vector_size (data_); break; + case x_int32: sz = get_vector_size (data_); break; + case x_uint32: sz = get_vector_size (data_); break; + case x_int64: sz = get_vector_size (data_); break; + case x_uint64: sz = get_vector_size (data_); break; case x_double: sz = get_vector_size (data_); break; case x_stdstring: sz = get_vector_size (data_); break; case x_stdtm: sz = get_vector_size (data_); break; From f27f14440d94aea03d97821da2a7d5fe46baec6e Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Tue, 5 Apr 2022 23:10:46 +0200 Subject: [PATCH 03/46] Update SQLite3 backend for complete integer type support --- include/soci/sqlite3/soci-sqlite3.h | 20 +- src/backends/sqlite3/standard-into-type.cpp | 52 ++++- src/backends/sqlite3/standard-use-type.cpp | 48 ++-- src/backends/sqlite3/statement.cpp | 85 +++++-- src/backends/sqlite3/vector-into-type.cpp | 231 ++++++++++++++++---- src/backends/sqlite3/vector-use-type.cpp | 73 +++++-- 6 files changed, 393 insertions(+), 116 deletions(-) diff --git a/include/soci/sqlite3/soci-sqlite3.h b/include/soci/sqlite3/soci-sqlite3.h index 2520dfd4b..3d2a62794 100644 --- a/include/soci/sqlite3/soci-sqlite3.h +++ b/include/soci/sqlite3/soci-sqlite3.h @@ -17,6 +17,7 @@ #endif #include +#include #include #include @@ -174,8 +175,14 @@ struct sqlite3_column union { sqlite3_column_buffer buffer_; - int int32_; + 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_; }; }; @@ -318,9 +325,14 @@ struct sqlite3_session_backend : details::session_backend case dt_double: return "real"; case dt_date: - case dt_integer: - case dt_long_long: - case dt_unsigned_long_long: + case dt_int8: + case dt_uint8: + case dt_int16: + case dt_uint16: + case dt_int32: + case dt_uint32: + case dt_int64: + case dt_uint64: return "integer"; case dt_blob: return "blob"; diff --git a/src/backends/sqlite3/standard-into-type.cpp b/src/backends/sqlite3/standard-into-type.cpp index 7d22d9b25..a5e581e9b 100644 --- a/src/backends/sqlite3/standard-into-type.cpp +++ b/src/backends/sqlite3/standard-into-type.cpp @@ -96,30 +96,58 @@ void sqlite3_standard_into_type_backend::post_fetch(bool gotData, break; } - case x_short: - exchange_type_cast(data_) - = static_cast::value_type >( + case x_int8: + exchange_type_cast(data_) + = static_cast::value_type >( sqlite3_column_int(statement_.stmt_, pos) ); break; - case x_integer: - exchange_type_cast(data_) - = static_cast::value_type >( + case x_uint8: + exchange_type_cast(data_) + = static_cast::value_type >( + sqlite3_column_int(statement_.stmt_, pos) + ); + break; + + case x_int16: + exchange_type_cast(data_) + = static_cast::value_type >( + sqlite3_column_int(statement_.stmt_, pos) + ); + break; + + case x_uint16: + exchange_type_cast(data_) + = static_cast::value_type >( + sqlite3_column_int(statement_.stmt_, pos) + ); + break; + + case x_int32: + exchange_type_cast(data_) + = static_cast::value_type >( sqlite3_column_int(statement_.stmt_, pos) ); break; - case x_long_long: - exchange_type_cast(data_) - = static_cast::value_type >( + case x_uint32: + exchange_type_cast(data_) + = static_cast::value_type >( + sqlite3_column_int(statement_.stmt_, pos) + ); + break; + + case x_int64: + exchange_type_cast(data_) + = static_cast::value_type >( sqlite3_column_int64(statement_.stmt_, pos) ); break; - case x_unsigned_long_long: - exchange_type_cast(data_) - = static_cast::value_type >( + case x_uint64: + exchange_type_cast(data_) + = static_cast::value_type >( sqlite3_column_int64(statement_.stmt_, pos) ); break; diff --git a/src/backends/sqlite3/standard-use-type.cpp b/src/backends/sqlite3/standard-use-type.cpp index adbb0581e..c8d502545 100644 --- a/src/backends/sqlite3/standard-use-type.cpp +++ b/src/backends/sqlite3/standard-use-type.cpp @@ -26,7 +26,7 @@ using namespace soci::details; sqlite3_standard_use_type_backend::sqlite3_standard_use_type_backend( sqlite3_statement_backend &st) - : statement_(st), data_(NULL), type_(x_integer), position_(-1) + : statement_(st), data_(NULL), type_(x_int32), position_(-1) { } @@ -112,24 +112,44 @@ void sqlite3_standard_use_type_backend::pre_use(indicator const * ind) break; } - case x_short: - col.type_ = dt_integer; - col.int32_ = exchange_type_cast(data_); + case x_int8: + col.type_ = dt_int8; + col.int8_ = exchange_type_cast(data_); break; - case x_integer: - col.type_ = dt_integer; - col.int32_ = exchange_type_cast(data_); + case x_uint8: + col.type_ = dt_uint8; + col.uint8_ = exchange_type_cast(data_); break; - case x_long_long: - col.type_ = dt_long_long; - col.int64_ = exchange_type_cast(data_); + case x_int16: + col.type_ = dt_int16; + col.int16_ = exchange_type_cast(data_); break; - case x_unsigned_long_long: - col.type_ = dt_long_long; - col.int64_ = exchange_type_cast(data_); + case x_uint16: + col.type_ = dt_uint16; + col.uint16_ = exchange_type_cast(data_); + break; + + case x_int32: + col.type_ = dt_int32; + col.int32_ = exchange_type_cast(data_); + break; + + case x_uint32: + col.type_ = dt_uint32; + col.uint32_ = exchange_type_cast(data_); + break; + + case x_int64: + col.type_ = dt_int64; + col.int64_ = exchange_type_cast(data_); + break; + + case x_uint64: + col.type_ = dt_uint64; + col.uint64_ = exchange_type_cast(data_); break; case x_double: @@ -155,7 +175,7 @@ void sqlite3_standard_use_type_backend::pre_use(indicator const * ind) case x_rowid: { - col.type_ = dt_long_long; + col.type_ = dt_int64; // RowID is internally identical to unsigned long rowid *rid = static_cast(data_); sqlite3_rowid_backend *rbe = static_cast(rid->get_backend()); diff --git a/src/backends/sqlite3/statement.cpp b/src/backends/sqlite3/statement.cpp index b97c7e694..fa5fc7439 100644 --- a/src/backends/sqlite3/statement.cpp +++ b/src/backends/sqlite3/statement.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #ifdef _MSC_VER @@ -177,14 +178,30 @@ sqlite3_statement_backend::load_rowset(int totalRows) col.double_ = sqlite3_column_double(stmt_, c); break; - case dt_integer: - col.int32_ = sqlite3_column_int(stmt_, c); + case dt_int8: + col.int8_ = static_cast(sqlite3_column_int(stmt_, c)); break; - - case dt_long_long: - case dt_unsigned_long_long: + case dt_uint8: + col.uint8_ = static_cast(sqlite3_column_int(stmt_, c)); + break; + case dt_int16: + col.int16_ = static_cast(sqlite3_column_int(stmt_, c)); + break; + case dt_uint16: + col.uint16_ = static_cast(sqlite3_column_int(stmt_, c)); + break; + case dt_int32: + col.int32_ = static_cast(sqlite3_column_int(stmt_, c)); + break; + case dt_uint32: + col.uint32_ = static_cast(sqlite3_column_int(stmt_, c)); + break; + case dt_int64: col.int64_ = sqlite3_column_int64(stmt_, c); break; + case dt_uint64: + col.uint64_ = static_cast(sqlite3_column_int64(stmt_, c)); + break; case dt_blob: col.buffer_.size_ = sqlite3_column_bytes(stmt_, c); @@ -283,14 +300,30 @@ sqlite3_statement_backend::bind_and_execute(int number) bindRes = sqlite3_bind_double(stmt_, pos, col.double_); break; - case dt_integer: - bindRes = sqlite3_bind_int(stmt_, pos, col.int32_); + case dt_int8: + bindRes = sqlite3_bind_int(stmt_, pos, static_cast(col.int8_)); break; - - case dt_long_long: - case dt_unsigned_long_long: + case dt_uint8: + bindRes = sqlite3_bind_int(stmt_, pos, static_cast(col.uint8_)); + break; + case dt_int16: + bindRes = sqlite3_bind_int(stmt_, pos, static_cast(col.int16_)); + break; + case dt_uint16: + bindRes = sqlite3_bind_int(stmt_, pos, static_cast(col.uint16_)); + break; + case dt_int32: + bindRes = sqlite3_bind_int(stmt_, pos, static_cast(col.int32_)); + break; + case dt_uint32: + bindRes = sqlite3_bind_int64(stmt_, pos, static_cast(col.uint32_)); + break; + case dt_int64: bindRes = sqlite3_bind_int64(stmt_, pos, col.int64_); break; + case dt_uint64: + bindRes = sqlite3_bind_int64(stmt_, pos, static_cast(col.int64_)); + break; case dt_blob: bindRes = sqlite3_bind_blob(stmt_, pos, col.buffer_.constData_, static_cast(col.buffer_.size_), NULL); @@ -433,18 +466,22 @@ static sqlite3_data_type_map get_data_type_map() m["numeric"] = dt_double; m["real"] = dt_double; - // dt_integer - m["boolean"] = dt_integer; - m["int"] = dt_integer; - m["integer"] = dt_integer; - m["int2"] = dt_integer; - m["mediumint"] = dt_integer; - m["smallint"] = dt_integer; - m["tinyint"] = dt_integer; + // dt_int8 + m["tinyint"] = dt_int8; + + // dt_int16 + m["smallint"] = dt_int16; + + // dt_int32 + m["boolean"] = dt_int32; + m["int"] = dt_int32; + m["integer"] = dt_int32; + m["int2"] = dt_int32; + m["mediumint"] = dt_int32; - // dt_long_long - m["bigint"] = dt_long_long; - m["int8"] = dt_long_long; + // dt_int64 + m["bigint"] = dt_int64; + m["int8"] = dt_int64; // dt_string m["char"] = dt_string; @@ -457,8 +494,8 @@ static sqlite3_data_type_map get_data_type_map() m["varchar"] = dt_string; m["varyingcharacter"] = dt_string; - // dt_unsigned_long_long - m["unsignedbigint"] = dt_unsigned_long_long; + // dt_uint64 + m["unsignedbigint"] = dt_uint64; return m; @@ -524,7 +561,7 @@ void sqlite3_statement_backend::describe_column(int colNum, data_type & type, switch (sqlite3_type) { case SQLITE_INTEGER: - type = dt_integer; + type = dt_int32; break; case SQLITE_FLOAT: type = dt_double; diff --git a/src/backends/sqlite3/vector-into-type.cpp b/src/backends/sqlite3/vector-into-type.cpp index 8feb99d00..e38659a84 100644 --- a/src/backends/sqlite3/vector-into-type.cpp +++ b/src/backends/sqlite3/vector-into-type.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -102,14 +103,30 @@ void set_number_in_vector(void *p, int idx, const sqlite3_column &col) set_in_vector(p, idx, static_cast(col.double_)); break; - case dt_integer: + case dt_int8: + set_in_vector(p, idx, static_cast(col.int8_)); + break; + case dt_uint8: + set_in_vector(p, idx, static_cast(col.uint8_)); + break; + case dt_int16: + set_in_vector(p, idx, static_cast(col.int16_)); + break; + case dt_uint16: + set_in_vector(p, idx, static_cast(col.uint16_)); + break; + case dt_int32: set_in_vector(p, idx, static_cast(col.int32_)); break; - - case dt_long_long: - case dt_unsigned_long_long: + case dt_uint32: + set_in_vector(p, idx, static_cast(col.uint32_)); + break; + case dt_int64: set_in_vector(p, idx, static_cast(col.int64_)); break; + case dt_uint64: + set_in_vector(p, idx, static_cast(col.uint64_)); + break; case dt_xml: throw soci_error("XML data type is not supported"); @@ -167,22 +184,62 @@ void sqlite3_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) set_in_vector(data_, i, double_to_cstring(col.double_)[0]); break; - case dt_integer: + case dt_int8: + { + std::ostringstream ss; + ss << col.int8_; + set_in_vector(data_, i, ss.str()[0]); + break; + } + case dt_uint8: + { + std::ostringstream ss; + ss << col.uint8_; + set_in_vector(data_, i, ss.str()[0]); + break; + } + case dt_int16: + { + std::ostringstream ss; + ss << col.int16_; + set_in_vector(data_, i, ss.str()[0]); + break; + } + case dt_uint16: + { + std::ostringstream ss; + ss << col.uint16_; + set_in_vector(data_, i, ss.str()[0]); + break; + } + case dt_int32: { std::ostringstream ss; ss << col.int32_; set_in_vector(data_, i, ss.str()[0]); break; } - - case dt_long_long: - case dt_unsigned_long_long: + case dt_uint32: + { + std::ostringstream ss; + ss << col.uint32_; + set_in_vector(data_, i, ss.str()[0]); + break; + } + case dt_int64: { std::ostringstream ss; ss << col.int64_; set_in_vector(data_, i, ss.str()[0]); break; } + case dt_uint64: + { + std::ostringstream ss; + ss << col.uint64_; + set_in_vector(data_, i, ss.str()[0]); + break; + } case dt_xml: throw soci_error("XML data type is not supported"); @@ -204,22 +261,62 @@ void sqlite3_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) set_in_vector(data_, i, double_to_cstring(col.double_)); break; - case dt_integer: + case dt_int8: + { + std::ostringstream ss; + ss << col.int8_; + set_in_vector(data_, i, ss.str()); + break; + } + case dt_uint8: + { + std::ostringstream ss; + ss << col.uint8_; + set_in_vector(data_, i, ss.str()); + break; + } + case dt_int16: + { + std::ostringstream ss; + ss << col.int16_; + set_in_vector(data_, i, ss.str()); + break; + } + case dt_uint16: + { + std::ostringstream ss; + ss << col.uint16_; + set_in_vector(data_, i, ss.str()); + break; + } + case dt_int32: { std::ostringstream ss; ss << col.int32_; set_in_vector(data_, i, ss.str()); break; } - - case dt_long_long: - case dt_unsigned_long_long: + case dt_uint32: + { + std::ostringstream ss; + ss << col.uint32_; + set_in_vector(data_, i, ss.str()); + break; + } + case dt_int64: { std::ostringstream ss; ss << col.int64_; set_in_vector(data_, i, ss.str()); break; } + case dt_uint64: + { + std::ostringstream ss; + ss << col.uint64_; + set_in_vector(data_, i, ss.str()); + break; + } case dt_xml: { @@ -251,20 +348,36 @@ void sqlite3_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) break; } // x_xmltype - case x_short: - set_number_in_vector::value_type>(data_, i, col); + case x_int8: + set_number_in_vector::value_type>(data_, i, col); + break; + + case x_uint8: + set_number_in_vector::value_type>(data_, i, col); + break; + + case x_int16: + set_number_in_vector::value_type>(data_, i, col); + break; + + case x_uint16: + set_number_in_vector::value_type>(data_, i, col); break; - case x_integer: - set_number_in_vector::value_type>(data_, i, col); + case x_int32: + set_number_in_vector::value_type>(data_, i, col); break; - case x_long_long: - set_number_in_vector::value_type>(data_, i, col); + case x_uint32: + set_number_in_vector::value_type>(data_, i, col); break; - case x_unsigned_long_long: - set_number_in_vector::value_type>(data_, i, col); + case x_int64: + set_number_in_vector::value_type>(data_, i, col); + break; + + case x_uint64: + set_number_in_vector::value_type>(data_, i, col); break; case x_double: @@ -288,9 +401,14 @@ void sqlite3_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) } case dt_double: - case dt_integer: - case dt_long_long: - case dt_unsigned_long_long: + case dt_int8: + case dt_uint8: + case dt_int16: + case dt_uint16: + case dt_int32: + case dt_uint32: + case dt_int64: + case dt_uint64: throw soci_error("Into element used with non-convertible type."); case dt_xml: @@ -314,9 +432,14 @@ void sqlite3_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) break; case dt_double: - case dt_integer: - case dt_long_long: - case dt_unsigned_long_long: + case dt_int8: + case dt_uint8: + case dt_int16: + case dt_uint16: + case dt_int32: + case dt_uint32: + case dt_int64: + case dt_uint64: break; case dt_xml: @@ -336,17 +459,29 @@ void sqlite3_vector_into_type_backend::resize(std::size_t sz) case x_char: resize_vector(data_, sz); break; - case x_short: - resize_vector(data_, sz); + case x_int8: + resize_vector(data_, sz); + break; + case x_uint8: + resize_vector(data_, sz); + break; + case x_int16: + resize_vector(data_, sz); + break; + case x_uint16: + resize_vector(data_, sz); break; - case x_integer: - resize_vector(data_, sz); + case x_int32: + resize_vector(data_, sz); break; - case x_long_long: - resize_vector(data_, sz); + case x_uint32: + resize_vector(data_, sz); break; - case x_unsigned_long_long: - resize_vector(data_, sz); + case x_int64: + resize_vector(data_, sz); + break; + case x_uint64: + resize_vector(data_, sz); break; case x_double: resize_vector(data_, sz); @@ -377,17 +512,29 @@ std::size_t sqlite3_vector_into_type_backend::size() case x_char: sz = get_vector_size(data_); break; - case x_short: - sz = get_vector_size(data_); + case x_int8: + sz = get_vector_size(data_); + break; + case x_uint8: + sz = get_vector_size(data_); + break; + case x_int16: + sz = get_vector_size(data_); + break; + case x_uint16: + sz = get_vector_size(data_); + break; + case x_int32: + sz = get_vector_size(data_); break; - case x_integer: - sz = get_vector_size(data_); + case x_uint32: + sz = get_vector_size(data_); break; - case x_long_long: - sz = get_vector_size(data_); + case x_int64: + sz = get_vector_size(data_); break; - case x_unsigned_long_long: - sz = get_vector_size(data_); + case x_uint64: + sz = get_vector_size(data_); break; case x_double: sz = get_vector_size(data_); diff --git a/src/backends/sqlite3/vector-use-type.cpp b/src/backends/sqlite3/vector-use-type.cpp index c98a3abf9..9962d7bf1 100644 --- a/src/backends/sqlite3/vector-use-type.cpp +++ b/src/backends/sqlite3/vector-use-type.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -111,24 +112,44 @@ void sqlite3_vector_use_type_backend::pre_use(indicator const * ind) break; } - case x_short: - col.type_ = dt_integer; - col.int32_ = (*static_cast::value_type> *>(data_))[i]; + case x_int8: + col.type_ = dt_int8; + col.int8_ = (*static_cast::value_type> *>(data_))[i]; break; - case x_integer: - col.type_ = dt_integer; - col.int32_ = (*static_cast::value_type> *>(data_))[i]; + case x_uint8: + col.type_ = dt_uint8; + col.uint8_ = (*static_cast::value_type> *>(data_))[i]; break; - case x_long_long: - col.type_ = dt_long_long; - col.int64_ = (*static_cast::value_type> *>(data_))[i]; + case x_int16: + col.type_ = dt_int16; + col.int16_ = (*static_cast::value_type> *>(data_))[i]; break; - case x_unsigned_long_long: - col.type_ = dt_long_long; - col.int64_ = (*static_cast::value_type> *>(data_))[i]; + case x_uint16: + col.type_ = dt_uint16; + col.uint16_ = (*static_cast::value_type> *>(data_))[i]; + break; + + case x_int32: + col.type_ = dt_int32; + col.int32_ = (*static_cast::value_type> *>(data_))[i]; + break; + + case x_uint32: + col.type_ = dt_uint32; + col.uint32_ = (*static_cast::value_type> *>(data_))[i]; + break; + + case x_int64: + col.type_ = dt_int64; + col.int64_ = (*static_cast::value_type> *>(data_))[i]; + break; + + case x_uint64: + col.type_ = dt_uint64; + col.uint64_ = (*static_cast::value_type> *>(data_))[i]; break; case x_double: @@ -176,17 +197,29 @@ std::size_t sqlite3_vector_use_type_backend::size() case x_char: sz = get_vector_size(data_); break; - case x_short: - sz = get_vector_size(data_); + case x_int8: + sz = get_vector_size(data_); + break; + case x_uint8: + sz = get_vector_size(data_); + break; + case x_int16: + sz = get_vector_size(data_); + break; + case x_uint16: + sz = get_vector_size(data_); + break; + case x_int32: + sz = get_vector_size(data_); break; - case x_integer: - sz = get_vector_size(data_); + case x_uint32: + sz = get_vector_size(data_); break; - case x_long_long: - sz = get_vector_size(data_); + case x_int64: + sz = get_vector_size(data_); break; - case x_unsigned_long_long: - sz = get_vector_size(data_); + case x_uint64: + sz = get_vector_size(data_); break; case x_double: sz = get_vector_size(data_); From dd45b6da3d7920191969e31b52387f0402f896a8 Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Tue, 5 Apr 2022 23:11:39 +0200 Subject: [PATCH 04/46] Update PostgreSQL backend for complete integer type support --- .../postgresql/standard-into-type.cpp | 29 ++-- src/backends/postgresql/standard-use-type.cpp | 61 ++++++-- src/backends/postgresql/statement.cpp | 9 +- src/backends/postgresql/vector-into-type.cpp | 99 +++++++++---- src/backends/postgresql/vector-use-type.cpp | 133 +++++++++++++----- 5 files changed, 251 insertions(+), 80 deletions(-) diff --git a/src/backends/postgresql/standard-into-type.cpp b/src/backends/postgresql/standard-into-type.cpp index b21cfbb57..7bd50467c 100644 --- a/src/backends/postgresql/standard-into-type.cpp +++ b/src/backends/postgresql/standard-into-type.cpp @@ -22,6 +22,7 @@ #include #include #include +#include using namespace soci; using namespace soci::details; @@ -90,17 +91,29 @@ void postgresql_standard_into_type_backend::post_fetch( case x_stdstring: exchange_type_cast(data_) = buf; break; - case x_short: - exchange_type_cast(data_) = string_to_integer(buf); + case x_int8: + exchange_type_cast(data_) = string_to_integer(buf); break; - case x_integer: - exchange_type_cast(data_) = string_to_integer(buf); + case x_uint8: + exchange_type_cast(data_) = string_to_integer(buf); break; - case x_long_long: - exchange_type_cast(data_) = string_to_integer(buf); + case x_int16: + exchange_type_cast(data_) = string_to_integer(buf); break; - case x_unsigned_long_long: - exchange_type_cast(data_) = string_to_unsigned_integer(buf); + case x_uint16: + exchange_type_cast(data_) = string_to_integer(buf); + break; + case x_int32: + exchange_type_cast(data_) = string_to_integer(buf); + break; + case x_uint32: + exchange_type_cast(data_) = string_to_integer(buf); + break; + case x_int64: + exchange_type_cast(data_) = string_to_integer(buf); + break; + case x_uint64: + exchange_type_cast(data_) = string_to_unsigned_integer(buf); break; case x_double: exchange_type_cast(data_) = cstring_to_double(buf); diff --git a/src/backends/postgresql/standard-use-type.cpp b/src/backends/postgresql/standard-use-type.cpp index c032fec95..ff71996fa 100644 --- a/src/backends/postgresql/standard-use-type.cpp +++ b/src/backends/postgresql/standard-use-type.cpp @@ -20,6 +20,7 @@ #include #include #include +#include using namespace soci; using namespace soci::details; @@ -67,40 +68,76 @@ void postgresql_standard_use_type_backend::pre_use(indicator const * ind) case x_stdstring: copy_from_string(exchange_type_cast(data_)); break; - case x_short: + case x_int8: { std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; snprintf(buf_, bufSize, "%d", - static_cast(exchange_type_cast(data_))); + static_cast(exchange_type_cast(data_))); } break; - case x_integer: + case x_uint8: { std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; + buf_ = new char[bufSize]; + snprintf(buf_, bufSize, "%u", + static_cast(exchange_type_cast(data_))); + } + break; + case x_int16: + { + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; snprintf(buf_, bufSize, "%d", - exchange_type_cast(data_)); + static_cast(exchange_type_cast(data_))); + } + break; + case x_uint16: + { + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf_ = new char[bufSize]; + snprintf(buf_, bufSize, "%u", + static_cast(exchange_type_cast(data_))); + } + break; + case x_int32: + { + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf_ = new char[bufSize]; + snprintf(buf_, bufSize, "%d", + static_cast(exchange_type_cast(data_))); + } + break; + case x_uint32: + { + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf_ = new char[bufSize]; + snprintf(buf_, bufSize, "%u", + static_cast(exchange_type_cast(data_))); } break; - case x_long_long: + case x_int64: { std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; snprintf(buf_, bufSize, "%" LL_FMT_FLAGS "d", - exchange_type_cast(data_)); + static_cast(exchange_type_cast(data_))); } break; - case x_unsigned_long_long: + case x_uint64: { std::size_t const bufSize - = std::numeric_limits::digits10 + 2; + = std::numeric_limits::digits10 + 2; buf_ = new char[bufSize]; snprintf(buf_, bufSize, "%" LL_FMT_FLAGS "u", - exchange_type_cast(data_)); + static_cast(exchange_type_cast(data_))); } break; case x_double: diff --git a/src/backends/postgresql/statement.cpp b/src/backends/postgresql/statement.cpp index a3b20339c..026ad7b99 100644 --- a/src/backends/postgresql/statement.cpp +++ b/src/backends/postgresql/statement.cpp @@ -783,15 +783,18 @@ void postgresql_statement_backend::describe_column(int colNum, data_type & type, type = dt_double; break; - case 16: // bool case 21: // int2 + type = dt_int16; + break; + + case 16: // bool case 23: // int4 case 26: // oid - type = dt_integer; + type = dt_int32; break; case 20: // int8 - type = dt_long_long; + type = dt_int64; break; default: diff --git a/src/backends/postgresql/vector-into-type.cpp b/src/backends/postgresql/vector-into-type.cpp index cd024884f..d852dac39 100644 --- a/src/backends/postgresql/vector-into-type.cpp +++ b/src/backends/postgresql/vector-into-type.cpp @@ -18,6 +18,7 @@ #include #include #include +#include using namespace soci; using namespace soci::details; @@ -115,28 +116,52 @@ void postgresql_vector_into_type_backend::post_fetch(bool gotData, indicator * i case x_stdstring: set_invector_(data_, i, buf); break; - case x_short: + case x_int8: { - short const val = string_to_integer(buf); + int8_t const val = string_to_integer(buf); set_invector_(data_, i, val); } break; - case x_integer: + case x_uint8: { - int const val = string_to_integer(buf); + uint8_t const val = string_to_integer(buf); set_invector_(data_, i, val); } break; - case x_long_long: + case x_int16: { - long long const val = string_to_integer(buf); + int16_t const val = string_to_integer(buf); set_invector_(data_, i, val); } break; - case x_unsigned_long_long: + case x_uint16: { - unsigned long long const val = - string_to_unsigned_integer(buf); + uint16_t const val = string_to_integer(buf); + set_invector_(data_, i, val); + } + break; + case x_int32: + { + int32_t const val = string_to_integer(buf); + set_invector_(data_, i, val); + } + break; + case x_uint32: + { + uint32_t const val = string_to_integer(buf); + set_invector_(data_, i, val); + } + break; + case x_int64: + { + int64_t const val = string_to_integer(buf); + set_invector_(data_, i, val); + } + break; + case x_uint64: + { + uint64_t val = + string_to_unsigned_integer(buf); set_invector_(data_, i, val); } break; @@ -199,17 +224,29 @@ void postgresql_vector_into_type_backend::resize(std::size_t sz) case x_char: resizevector_(data_, sz); break; - case x_short: - resizevector_(data_, sz); + case x_int8: + resizevector_(data_, sz); + break; + case x_uint8: + resizevector_(data_, sz); + break; + case x_int16: + resizevector_(data_, sz); break; - case x_integer: - resizevector_(data_, sz); + case x_uint16: + resizevector_(data_, sz); break; - case x_long_long: - resizevector_(data_, sz); + case x_int32: + resizevector_(data_, sz); break; - case x_unsigned_long_long: - resizevector_(data_, sz); + case x_uint32: + resizevector_(data_, sz); + break; + case x_int64: + resizevector_(data_, sz); + break; + case x_uint64: + resizevector_(data_, sz); break; case x_double: resizevector_(data_, sz); @@ -267,17 +304,29 @@ std::size_t postgresql_vector_into_type_backend::full_size() case x_char: sz = get_vector_size(data_); break; - case x_short: - sz = get_vector_size(data_); + case x_int8: + sz = get_vector_size(data_); + break; + case x_uint8: + sz = get_vector_size(data_); + break; + case x_int16: + sz = get_vector_size(data_); + break; + case x_uint16: + sz = get_vector_size(data_); + break; + case x_int32: + sz = get_vector_size(data_); break; - case x_integer: - sz = get_vector_size(data_); + case x_uint32: + sz = get_vector_size(data_); break; - case x_long_long: - sz = get_vector_size(data_); + case x_int64: + sz = get_vector_size(data_); break; - case x_unsigned_long_long: - sz = get_vector_size(data_); + case x_uint64: + sz = get_vector_size(data_); break; case x_double: sz = get_vector_size(data_); diff --git a/src/backends/postgresql/vector-use-type.cpp b/src/backends/postgresql/vector-use-type.cpp index 3af7ae73e..1487b191a 100644 --- a/src/backends/postgresql/vector-use-type.cpp +++ b/src/backends/postgresql/vector-use-type.cpp @@ -18,6 +18,7 @@ #include #include #include +#include using namespace soci; using namespace soci::details; @@ -98,52 +99,108 @@ void postgresql_vector_use_type_backend::pre_use(indicator const * ind) std::strcpy(buf, v[i].c_str()); } break; - case x_short: + case x_int8: { - std::vector * pv - = static_cast *>(data_); - std::vector & v = *pv; + std::vector * pv + = static_cast *>(data_); + std::vector & v = *pv; std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%d", static_cast(v[i])); + snprintf(buf, bufSize, "%d", + static_cast(v[i])); } break; - case x_integer: + case x_uint8: { - std::vector * pv - = static_cast *>(data_); - std::vector & v = *pv; + std::vector * pv + = static_cast *>(data_); + std::vector & v = *pv; std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%d", v[i]); + snprintf(buf, bufSize, "%u", + static_cast(v[i])); } break; - case x_long_long: + case x_int16: { - std::vector* pv - = static_cast*>(data_); - std::vector& v = *pv; + std::vector * pv + = static_cast *>(data_); + std::vector & v = *pv; std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%" LL_FMT_FLAGS "d", v[i]); + snprintf(buf, bufSize, "%d", + static_cast(v[i])); } break; - case x_unsigned_long_long: + case x_uint16: { - std::vector* pv - = static_cast*>(data_); - std::vector& v = *pv; + std::vector * pv + = static_cast *>(data_); + std::vector & v = *pv; std::size_t const bufSize - = std::numeric_limits::digits10 + 2; + = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%" LL_FMT_FLAGS "u", v[i]); + snprintf(buf, bufSize, "%u", + static_cast(v[i])); + } + break; + case x_int32: + { + std::vector * pv + = static_cast *>(data_); + std::vector & v = *pv; + + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf = new char[bufSize]; + snprintf(buf, bufSize, "%d", + static_cast(v[i])); + } + break; + case x_uint32: + { + std::vector * pv + = static_cast *>(data_); + std::vector & v = *pv; + + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf = new char[bufSize]; + snprintf(buf, bufSize, "%u", + static_cast(v[i])); + } + break; + case x_int64: + { + std::vector* pv + = static_cast*>(data_); + std::vector& v = *pv; + + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf = new char[bufSize]; + snprintf(buf, bufSize, "%" LL_FMT_FLAGS "d", + static_cast(v[i])); + } + break; + case x_uint64: + { + std::vector* pv + = static_cast*>(data_); + std::vector& v = *pv; + + std::size_t const bufSize + = std::numeric_limits::digits10 + 2; + buf = new char[bufSize]; + snprintf(buf, bufSize, "%" LL_FMT_FLAGS "u", + static_cast(v[i])); } break; case x_double: @@ -244,17 +301,29 @@ std::size_t postgresql_vector_use_type_backend::full_size() case x_char: sz = get_vector_size(data_); break; - case x_short: - sz = get_vector_size(data_); + case x_int8: + sz = get_vector_size(data_); + break; + case x_uint8: + sz = get_vector_size(data_); + break; + case x_int16: + sz = get_vector_size(data_); + break; + case x_uint16: + sz = get_vector_size(data_); + break; + case x_int32: + sz = get_vector_size(data_); break; - case x_integer: - sz = get_vector_size(data_); + case x_uint32: + sz = get_vector_size(data_); break; - case x_long_long: - sz = get_vector_size(data_); + case x_int64: + sz = get_vector_size(data_); break; - case x_unsigned_long_long: - sz = get_vector_size(data_); + case x_uint64: + sz = get_vector_size(data_); break; case x_double: sz = get_vector_size(data_); From 8fc34db960ec947e21591d122f0dc752d0493c00 Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Tue, 5 Apr 2022 23:10:31 +0200 Subject: [PATCH 05/46] Update Oracle backend for complete integer type support --- include/soci/oracle/soci-oracle.h | 10 +- src/backends/oracle/standard-into-type.cpp | 37 +++-- src/backends/oracle/standard-use-type.cpp | 163 +++++++++++++++++---- src/backends/oracle/statement.cpp | 6 +- src/backends/oracle/vector-into-type.cpp | 79 +++++++--- src/backends/oracle/vector-use-type.cpp | 83 ++++++++--- 6 files changed, 297 insertions(+), 81 deletions(-) diff --git a/include/soci/oracle/soci-oracle.h b/include/soci/oracle/soci-oracle.h index 3dc52630d..255692a6b 100644 --- a/include/soci/oracle/soci-oracle.h +++ b/include/soci/oracle/soci-oracle.h @@ -374,15 +374,19 @@ struct oracle_session_backend : details::session_backend } break; - case dt_integer: + case dt_int16: + res += "smallint"; + break; + + case dt_int32: res += "integer"; break; - case dt_long_long: + case dt_int64: res += "number"; break; - case dt_unsigned_long_long: + case dt_uint64: res += "number"; break; diff --git a/src/backends/oracle/standard-into-type.cpp b/src/backends/oracle/standard-into-type.cpp index 8fa9750a2..3983d795c 100644 --- a/src/backends/oracle/standard-into-type.cpp +++ b/src/backends/oracle/standard-into-type.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #ifdef _MSC_VER #pragma warning(disable:4355) @@ -70,13 +71,29 @@ void oracle_standard_into_type_backend::define_by_pos( oracleType = SQLT_AFC; size = sizeof(char); break; - case x_short: + case x_int8: oracleType = SQLT_INT; - size = sizeof(short); + size = sizeof(int8_t); break; - case x_integer: + case x_uint8: + oracleType = SQLT_UIN; + size = sizeof(uint8_t); + break; + case x_int16: oracleType = SQLT_INT; - size = sizeof(int); + size = sizeof(int16_t); + break; + case x_uint16: + oracleType = SQLT_UIN; + size = sizeof(uint16_t); + break; + case x_int32: + oracleType = SQLT_INT; + size = sizeof(int32_t); + break; + case x_uint32: + oracleType = SQLT_UIN; + size = sizeof(uint32_t); break; case x_double: oracleType = statement_.session_.get_double_sql_type(); @@ -84,8 +101,8 @@ void oracle_standard_into_type_backend::define_by_pos( break; // cases that require adjustments and buffer management - case x_long_long: - case x_unsigned_long_long: + case x_int64: + case x_uint64: oracleType = SQLT_STR; size = 100; // arbitrary buffer length buf_ = new char[size]; @@ -248,18 +265,18 @@ void oracle_standard_into_type_backend::post_fetch( exchange_type_cast(data_) = buf_; } } - else if (type_ == x_long_long) + else if (type_ == x_int64) { if (indOCIHolder_ != -1) { - exchange_type_cast(data_) = std::strtoll(buf_, NULL, 10); + exchange_type_cast(data_) = std::strtoll(buf_, NULL, 10); } } - else if (type_ == x_unsigned_long_long) + else if (type_ == x_uint64) { if (indOCIHolder_ != -1) { - exchange_type_cast(data_) = std::strtoull(buf_, NULL, 10); + exchange_type_cast(data_) = std::strtoull(buf_, NULL, 10); } } else if (type_ == x_stdtm) diff --git a/src/backends/oracle/standard-use-type.cpp b/src/backends/oracle/standard-use-type.cpp index b25d6531c..3b3b51c33 100644 --- a/src/backends/oracle/standard-use-type.cpp +++ b/src/backends/oracle/standard-use-type.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #ifdef _MSC_VER #pragma warning(disable:4355) @@ -52,18 +53,54 @@ void oracle_standard_use_type_backend::prepare_for_bind( data = buf_; } break; - case x_short: + case x_int8: oracleType = SQLT_INT; - size = sizeof(short); + size = sizeof(int8_t); if (readOnly) { buf_ = new char[size]; data = buf_; } break; - case x_integer: + case x_uint8: + oracleType = SQLT_UIN; + size = sizeof(uint8_t); + if (readOnly) + { + buf_ = new char[size]; + data = buf_; + } + break; + case x_int16: + oracleType = SQLT_INT; + size = sizeof(int16_t); + if (readOnly) + { + buf_ = new char[size]; + data = buf_; + } + break; + case x_uint16: + oracleType = SQLT_UIN; + size = sizeof(uint16_t); + if (readOnly) + { + buf_ = new char[size]; + data = buf_; + } + break; + case x_int32: oracleType = SQLT_INT; - size = sizeof(int); + size = sizeof(int32_t); + if (readOnly) + { + buf_ = new char[size]; + data = buf_; + } + break; + case x_uint32: + oracleType = SQLT_UIN; + size = sizeof(uint32_t); if (readOnly) { buf_ = new char[size]; @@ -81,8 +118,8 @@ void oracle_standard_use_type_backend::prepare_for_bind( break; // cases that require adjustments and buffer management - case x_long_long: - case x_unsigned_long_long: + case x_int64: + case x_uint64: oracleType = SQLT_STR; size = 100; // arbitrary buffer length buf_ = new char[size]; @@ -333,28 +370,54 @@ void oracle_standard_use_type_backend::pre_use(indicator const *ind) buf_[0] = exchange_type_cast(data_); } break; - case x_short: + case x_int8: if (readOnly_) { - exchange_type_cast(buf_) = exchange_type_cast(data_); + exchange_type_cast(buf_) = exchange_type_cast(data_); } break; - case x_integer: + case x_uint8: if (readOnly_) { - exchange_type_cast(buf_) = exchange_type_cast(data_); + exchange_type_cast(buf_) = exchange_type_cast(data_); } break; - case x_long_long: + case x_int16: + if (readOnly_) + { + exchange_type_cast(buf_) = exchange_type_cast(data_); + } + break; + case x_uint16: + if (readOnly_) + { + exchange_type_cast(buf_) = exchange_type_cast(data_); + } + break; + case x_int32: + if (readOnly_) + { + exchange_type_cast(buf_) = exchange_type_cast(data_); + } + break; + case x_uint32: + if (readOnly_) + { + exchange_type_cast(buf_) = exchange_type_cast(data_); + } + break; + case x_int64: { size_t const size = 100; // arbitrary, but consistent with prepare_for_bind - snprintf(buf_, size, "%" LL_FMT_FLAGS "d", exchange_type_cast(data_)); + snprintf(buf_, size, "%" LL_FMT_FLAGS "d", + static_cast(exchange_type_cast(data_))); } break; - case x_unsigned_long_long: + case x_uint64: { size_t const size = 100; // arbitrary, but consistent with prepare_for_bind - snprintf(buf_, size, "%" LL_FMT_FLAGS "u", exchange_type_cast(data_)); + snprintf(buf_, size, "%" LL_FMT_FLAGS "u", + static_cast(exchange_type_cast(data_))); } break; case x_double: @@ -442,11 +505,59 @@ void oracle_standard_use_type_backend::post_use(bool gotData, indicator *ind) } } break; - case x_short: + case x_int8: + if (readOnly_) + { + const int8_t original = exchange_type_cast(data_); + const int8_t bound = exchange_type_cast(buf_); + + if (original != bound) + { + throw soci_error("Attempted modification of const use element"); + } + } + break; + case x_uint8: + if (readOnly_) + { + const uint8_t original = exchange_type_cast(data_); + const uint8_t bound = exchange_type_cast(buf_); + + if (original != bound) + { + throw soci_error("Attempted modification of const use element"); + } + } + break; + case x_int16: + if (readOnly_) + { + const int16_t original = exchange_type_cast(data_); + const int16_t bound = exchange_type_cast(buf_); + + if (original != bound) + { + throw soci_error("Attempted modification of const use element"); + } + } + break; + case x_uint16: + if (readOnly_) + { + const uint16_t original = exchange_type_cast(data_); + const uint16_t bound = exchange_type_cast(buf_); + + if (original != bound) + { + throw soci_error("Attempted modification of const use element"); + } + } + break; + case x_int32: if (readOnly_) { - const short original = exchange_type_cast(data_); - const short bound = exchange_type_cast(buf_); + const int32_t original = exchange_type_cast(data_); + const int32_t bound = exchange_type_cast(buf_); if (original != bound) { @@ -454,11 +565,11 @@ void oracle_standard_use_type_backend::post_use(bool gotData, indicator *ind) } } break; - case x_integer: + case x_uint32: if (readOnly_) { - const int original = exchange_type_cast(data_); - const int bound = exchange_type_cast(buf_); + const uint32_t original = exchange_type_cast(data_); + const uint32_t bound = exchange_type_cast(buf_); if (original != bound) { @@ -466,11 +577,11 @@ void oracle_standard_use_type_backend::post_use(bool gotData, indicator *ind) } } break; - case x_long_long: + case x_int64: if (readOnly_) { - long long const original = exchange_type_cast(data_); - long long const bound = std::strtoll(buf_, NULL, 10); + int64_t const original = exchange_type_cast(data_); + int64_t const bound = std::strtoll(buf_, NULL, 10); if (original != bound) { @@ -478,11 +589,11 @@ void oracle_standard_use_type_backend::post_use(bool gotData, indicator *ind) } } break; - case x_unsigned_long_long: + case x_uint64: if (readOnly_) { - unsigned long long const original = exchange_type_cast(data_); - unsigned long long const bound = std::strtoull(buf_, NULL, 10); + uint64_t const original = exchange_type_cast(data_); + uint64_t const bound = std::strtoull(buf_, NULL, 10); if (original != bound) { diff --git a/src/backends/oracle/statement.cpp b/src/backends/oracle/statement.cpp index b0a4815cf..d6fa5f68e 100644 --- a/src/backends/oracle/statement.cpp +++ b/src/backends/oracle/statement.cpp @@ -299,13 +299,13 @@ void oracle_statement_backend::describe_column(int colNum, data_type &type, type = dt_double; } } - else if (dbprec <= std::numeric_limits::digits10) + else if (dbprec <= std::numeric_limits::digits10) { - type = dt_integer; + type = dt_int32; } else { - type = dt_long_long; + type = dt_int64; } break; case OCI_TYPECODE_BDOUBLE: diff --git a/src/backends/oracle/vector-into-type.cpp b/src/backends/oracle/vector-into-type.cpp index 23ddc52f8..baa295e0e 100644 --- a/src/backends/oracle/vector-into-type.cpp +++ b/src/backends/oracle/vector-into-type.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #ifdef _MSC_VER #pragma warning(disable:4355) @@ -69,22 +70,62 @@ void oracle_vector_into_type_backend::define_by_pos_bulk( dataBuf = &v[begin_]; } break; - case x_short: + case x_int8: { oracleType = SQLT_INT; - elementSize = sizeof(short); - std::vector *vp = static_cast *>(data); - std::vector &v(*vp); + elementSize = sizeof(int8_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); prepare_indicators(size()); dataBuf = &v[begin_]; } break; - case x_integer: + case x_uint8: + { + oracleType = SQLT_UIN; + elementSize = sizeof(uint8_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); + prepare_indicators(size()); + dataBuf = &v[begin_]; + } + break; + case x_int16: { oracleType = SQLT_INT; - elementSize = sizeof(int); - std::vector *vp = static_cast *>(data); - std::vector &v(*vp); + elementSize = sizeof(int16_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); + prepare_indicators(size()); + dataBuf = &v[begin_]; + } + break; + case x_uint16: + { + oracleType = SQLT_UIN; + elementSize = sizeof(uint16_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); + prepare_indicators(size()); + dataBuf = &v[begin_]; + } + break; + case x_int32: + { + oracleType = SQLT_INT; + elementSize = sizeof(int32_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); + prepare_indicators(size()); + dataBuf = &v[begin_]; + } + break; + case x_uint32: + { + oracleType = SQLT_UIN; + elementSize = sizeof(uint32_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); prepare_indicators(size()); dataBuf = &v[begin_]; } @@ -102,7 +143,7 @@ void oracle_vector_into_type_backend::define_by_pos_bulk( // cases that require adjustments and buffer management - case x_long_long: + case x_int64: { oracleType = SQLT_STR; const std::size_t vecSize = size(); @@ -116,7 +157,7 @@ void oracle_vector_into_type_backend::define_by_pos_bulk( dataBuf = buf_; } break; - case x_unsigned_long_long: + case x_uint64: { oracleType = SQLT_STR; const std::size_t vecSize = size(); @@ -216,7 +257,7 @@ void oracle_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) { // first, deal with data - // only std::string, std::tm, long long and Statement need special handling + // only std::string, std::tm, int64 and Statement need special handling if (type_ == x_stdstring) { std::vector *vp @@ -235,12 +276,12 @@ void oracle_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) pos += colSize_; } } - else if (type_ == x_long_long) + else if (type_ == x_int64) { - std::vector *vp - = static_cast *>(data_); + std::vector *vp + = static_cast *>(data_); - std::vector &v(*vp); + std::vector &v(*vp); char *pos = buf_; std::size_t const vecSize = size(); @@ -253,12 +294,12 @@ void oracle_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) pos += colSize_; } } - else if (type_ == x_unsigned_long_long) + else if (type_ == x_uint64) { - std::vector *vp - = static_cast *>(data_); + std::vector *vp + = static_cast *>(data_); - std::vector &v(*vp); + std::vector &v(*vp); char *pos = buf_; std::size_t const vecSize = size(); diff --git a/src/backends/oracle/vector-use-type.cpp b/src/backends/oracle/vector-use-type.cpp index b13eec2b6..069449a9f 100644 --- a/src/backends/oracle/vector-use-type.cpp +++ b/src/backends/oracle/vector-use-type.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #ifdef _MSC_VER #pragma warning(disable:4355) @@ -52,22 +53,62 @@ void oracle_vector_use_type_backend::prepare_for_bind( data = &v[begin_]; } break; - case x_short: + case x_int8: { oracleType = SQLT_INT; - elementSize = sizeof(short); - std::vector *vp = static_cast *>(data_); - std::vector &v(*vp); + elementSize = sizeof(int8_t); + std::vector *vp = static_cast *>(data_); + std::vector &v(*vp); prepare_indicators(size()); data = &v[begin_]; } break; - case x_integer: + case x_uint8: + { + oracleType = SQLT_UIN; + elementSize = sizeof(uint8_t); + std::vector *vp = static_cast *>(data_); + std::vector &v(*vp); + prepare_indicators(size()); + data = &v[begin_]; + } + break; + case x_int16: { oracleType = SQLT_INT; - elementSize = sizeof(int); - std::vector *vp = static_cast *>(data_); - std::vector &v(*vp); + elementSize = sizeof(int16_t); + std::vector *vp = static_cast *>(data_); + std::vector &v(*vp); + prepare_indicators(size()); + data = &v[begin_]; + } + break; + case x_uint16: + { + oracleType = SQLT_UIN; + elementSize = sizeof(uint16_t); + std::vector *vp = static_cast *>(data_); + std::vector &v(*vp); + prepare_indicators(size()); + data = &v[begin_]; + } + break; + case x_int32: + { + oracleType = SQLT_INT; + elementSize = sizeof(int32_t); + std::vector *vp = static_cast *>(data_); + std::vector &v(*vp); + prepare_indicators(size()); + data = &v[begin_]; + } + break; + case x_uint32: + { + oracleType = SQLT_UIN; + elementSize = sizeof(uint32_t); + std::vector *vp = static_cast *>(data_); + std::vector &v(*vp); prepare_indicators(size()); data = &v[begin_]; } @@ -85,7 +126,7 @@ void oracle_vector_use_type_backend::prepare_for_bind( // cases that require adjustments and buffer management - case x_long_long: + case x_int64: { std::size_t const vecSize = size(); std::size_t const entrySize = 100; // arbitrary @@ -99,7 +140,7 @@ void oracle_vector_use_type_backend::prepare_for_bind( prepare_indicators(vecSize); } break; - case x_unsigned_long_long: + case x_uint64: { std::size_t const vecSize = size(); std::size_t const entrySize = 100; // arbitrary @@ -225,33 +266,35 @@ void oracle_vector_use_type_backend::pre_use(indicator const *ind) { // nothing to do - already done in prepare_for_bind() } - else if (type_ == x_long_long) + else if (type_ == x_int64) { - std::vector *vp - = static_cast *>(data_); - std::vector &v(*vp); + std::vector *vp + = static_cast *>(data_); + std::vector &v(*vp); char *pos = buf_; std::size_t const entrySize = 100; // arbitrary, but consistent std::size_t const vecSize = size(); for (std::size_t i = 0; i != vecSize; ++i) { - snprintf(pos, entrySize, "%" LL_FMT_FLAGS "d", v[begin_ + i]); + snprintf(pos, entrySize, "%" LL_FMT_FLAGS "d", + static_cast(v[begin_ + i])); pos += entrySize; } } - else if (type_ == x_unsigned_long_long) + else if (type_ == x_uint64) { - std::vector *vp - = static_cast *>(data_); - std::vector &v(*vp); + std::vector *vp + = static_cast *>(data_); + std::vector &v(*vp); char *pos = buf_; std::size_t const entrySize = 100; // arbitrary, but consistent std::size_t const vecSize = size(); for (std::size_t i = 0; i != vecSize; ++i) { - snprintf(pos, entrySize, "%" LL_FMT_FLAGS "u", v[begin_ + i]); + snprintf(pos, entrySize, "%" LL_FMT_FLAGS "u", + static_cast(v[begin_ + i])); pos += entrySize; } } From 9d0d7c4454e4a2241fd6f74546d9cde6d77f63e2 Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Tue, 5 Apr 2022 23:10:56 +0200 Subject: [PATCH 06/46] Update DB2 backend for complete integer type support --- src/backends/db2/standard-into-type.cpp | 33 +++-- src/backends/db2/standard-use-type.cpp | 37 ++++-- src/backends/db2/statement.cpp | 8 +- src/backends/db2/vector-into-type.cpp | 155 +++++++++++++++++++----- src/backends/db2/vector-use-type.cpp | 125 ++++++++++++++----- 5 files changed, 279 insertions(+), 79 deletions(-) diff --git a/src/backends/db2/standard-into-type.cpp b/src/backends/db2/standard-into-type.cpp index 97e6db6ea..9558619ca 100644 --- a/src/backends/db2/standard-into-type.cpp +++ b/src/backends/db2/standard-into-type.cpp @@ -12,6 +12,7 @@ #include "soci-mktime.h" #include "common.h" #include +#include using namespace soci; using namespace soci::details; @@ -45,21 +46,37 @@ void db2_standard_into_type_backend::define_by_pos( buf = new char[size]; data = buf; break; - case x_short: + case x_int8: + cType = SQL_C_STINYINT; + size = sizeof(int8_t); + break; + case x_uint8: + cType = SQL_C_UTINYINT; + size = sizeof(uint8_t); + break; + case x_int16: cType = SQL_C_SSHORT; - size = sizeof(short); + size = sizeof(int16_t); break; - case x_integer: + case x_uint16: + cType = SQL_C_USHORT; + size = sizeof(uint16_t); + break; + case x_int32: cType = SQL_C_SLONG; size = sizeof(SQLINTEGER); break; - case x_long_long: + case x_uint32: + cType = SQL_C_ULONG; + size = sizeof(SQLUINTEGER); + break; + case x_int64: cType = SQL_C_SBIGINT; - size = sizeof(long long); + size = sizeof(int64_t); break; - case x_unsigned_long_long: + case x_uint64: cType = SQL_C_UBIGINT; - size = sizeof(unsigned long long); + size = sizeof(uint64_t); break; case x_double: cType = SQL_C_DOUBLE; @@ -73,7 +90,7 @@ void db2_standard_into_type_backend::define_by_pos( break; case x_rowid: cType = SQL_C_UBIGINT; - size = sizeof(unsigned long long); + size = sizeof(int64_t); break; default: throw soci_error("Into element used with non-supported type."); diff --git a/src/backends/db2/standard-use-type.cpp b/src/backends/db2/standard-use-type.cpp index 87dbd4698..44e1e70cd 100644 --- a/src/backends/db2/standard-use-type.cpp +++ b/src/backends/db2/standard-use-type.cpp @@ -14,6 +14,7 @@ #include #include #include +#include using namespace soci; using namespace soci::details; @@ -24,25 +25,45 @@ void *db2_standard_use_type_backend::prepare_for_bind( switch (type) { // simple cases - case x_short: + case x_int8: + sqlType = SQL_SMALLINT; + cType = SQL_C_STINYINT; + size = sizeof(int8_t); + break; + case x_uint8: + sqlType = SQL_SMALLINT; + cType = SQL_C_UTINYINT; + size = sizeof(uint8_t); + break; + case x_int16: sqlType = SQL_SMALLINT; cType = SQL_C_SSHORT; - size = sizeof(short); + size = sizeof(int16_t); break; - case x_integer: + case x_uint16: + sqlType = SQL_SMALLINT; + cType = SQL_C_USHORT; + size = sizeof(uint16_t); + break; + case x_int32: sqlType = SQL_INTEGER; cType = SQL_C_SLONG; - size = sizeof(int); + size = sizeof(int32_t); + break; + case x_uint32: + sqlType = SQL_INTEGER; + cType = SQL_C_ULONG; + size = sizeof(uint32_t); break; - case x_long_long: + case x_int64: sqlType = SQL_BIGINT; cType = SQL_C_SBIGINT; - size = sizeof(long long); + size = sizeof(int64_t); break; - case x_unsigned_long_long: + case x_uint64: sqlType = SQL_BIGINT; cType = SQL_C_UBIGINT; - size = sizeof(unsigned long long); + size = sizeof(uint64_t); break; case x_double: sqlType = SQL_DOUBLE; diff --git a/src/backends/db2/statement.cpp b/src/backends/db2/statement.cpp index 73b7432bb..f9c0b02b0 100644 --- a/src/backends/db2/statement.cpp +++ b/src/backends/db2/statement.cpp @@ -262,12 +262,16 @@ SQLCHAR colNameBuffer[2048]; type = dt_double; break; case SQL_TINYINT: + type = dt_int8; + break; case SQL_SMALLINT: + type = dt_int16; + break; case SQL_INTEGER: - type = dt_integer; + type = dt_int32; break; case SQL_BIGINT: - type = dt_long_long; + type = dt_int64; break; case SQL_CHAR: case SQL_VARCHAR: diff --git a/src/backends/db2/vector-into-type.cpp b/src/backends/db2/vector-into-type.cpp index 19362ec4a..8c6dc9bf6 100644 --- a/src/backends/db2/vector-into-type.cpp +++ b/src/backends/db2/vector-into-type.cpp @@ -14,6 +14,7 @@ #include #include #include +#include using namespace soci; using namespace soci::details; @@ -39,17 +40,47 @@ void db2_vector_into_type_backend::define_by_pos( switch (type) { // simple cases - case x_short: + case x_int8: + { + cType = SQL_C_STINYINT; + size = sizeof(int8_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); + prepare_indicators(v.size()); + data = &v[0]; + } + break; + case x_uint8: + { + cType = SQL_C_UTINYINT; + size = sizeof(uint8_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); + prepare_indicators(v.size()); + data = &v[0]; + } + break; + case x_int16: { cType = SQL_C_SSHORT; - size = sizeof(short); - std::vector *vp = static_cast *>(data); - std::vector &v(*vp); + size = sizeof(int16_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); + prepare_indicators(v.size()); + data = &v[0]; + } + break; + case x_uint16: + { + cType = SQL_C_USHORT; + size = sizeof(uint16_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); prepare_indicators(v.size()); data = &v[0]; } break; - case x_integer: + case x_int32: { cType = SQL_C_SLONG; size = sizeof(SQLINTEGER); @@ -59,24 +90,34 @@ void db2_vector_into_type_backend::define_by_pos( data = &v[0]; } break; - case x_long_long: + case x_uint32: + { + cType = SQL_C_ULONG; + size = sizeof(SQLUINTEGER); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); + prepare_indicators(v.size()); + data = &v[0]; + } + break; + case x_int64: { cType = SQL_C_SBIGINT; - size = sizeof(long long); - std::vector *vp - = static_cast *>(data); - std::vector &v(*vp); + size = sizeof(int64_t); + std::vector *vp + = static_cast *>(data); + std::vector &v(*vp); prepare_indicators(v.size()); data = &v[0]; } break; - case x_unsigned_long_long: + case x_uint64: { cType = SQL_C_UBIGINT; - size = sizeof(unsigned long long); - std::vector *vp - = static_cast *>(data); - std::vector &v(*vp); + size = sizeof(uint64_t); + std::vector *vp + = static_cast *>(data); + std::vector &v(*vp); prepare_indicators(v.size()); data = &v[0]; } @@ -286,29 +327,53 @@ void db2_vector_into_type_backend::resize(std::size_t sz) v->resize(sz); } break; - case x_short: + case x_int8: + { + std::vector *v = static_cast *>(data); + v->resize(sz); + } + break; + case x_uint8: + { + std::vector *v = static_cast *>(data); + v->resize(sz); + } + break; + case x_int16: { - std::vector *v = static_cast *>(data); + std::vector *v = static_cast *>(data); v->resize(sz); } break; - case x_integer: + case x_uint16: + { + std::vector *v = static_cast *>(data); + v->resize(sz); + } + break; + case x_int32: { std::vector *v = static_cast *>(data); v->resize(sz); } break; - case x_long_long: + case x_uint32: { - std::vector *v - = static_cast *>(data); + std::vector *v = static_cast *>(data); v->resize(sz); } break; - case x_unsigned_long_long: + case x_int64: { - std::vector *v - = static_cast *>(data); + std::vector *v + = static_cast *>(data); + v->resize(sz); + } + break; + case x_uint64: + { + std::vector *v + = static_cast *>(data); v->resize(sz); } break; @@ -354,29 +419,53 @@ std::size_t db2_vector_into_type_backend::size() sz = v->size(); } break; - case x_short: + case x_int8: + { + std::vector *v = static_cast *>(data); + sz = v->size(); + } + break; + case x_uint8: { - std::vector *v = static_cast *>(data); + std::vector *v = static_cast *>(data); sz = v->size(); } break; - case x_integer: + case x_int16: + { + std::vector *v = static_cast *>(data); + sz = v->size(); + } + break; + case x_uint16: + { + std::vector *v = static_cast *>(data); + sz = v->size(); + } + break; + case x_int32: { std::vector *v = static_cast *>(data); sz = v->size(); } break; - case x_long_long: + case x_uint32: + { + std::vector *v = static_cast *>(data); + sz = v->size(); + } + break; + case x_int64: { - std::vector *v - = static_cast *>(data); + std::vector *v + = static_cast *>(data); sz = v->size(); } break; - case x_unsigned_long_long: + case x_uint64: { - std::vector *v - = static_cast *>(data); + std::vector *v + = static_cast *>(data); sz = v->size(); } break; diff --git a/src/backends/db2/vector-use-type.cpp b/src/backends/db2/vector-use-type.cpp index a5f30f9b1..b75baf15d 100644 --- a/src/backends/db2/vector-use-type.cpp +++ b/src/backends/db2/vector-use-type.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #ifdef _MSC_VER // disables the warning about converting int to void*. This is a 64 bit compatibility @@ -42,48 +43,92 @@ void *db2_vector_use_type_backend::prepare_for_bind(SQLUINTEGER &size, void* sqlData = NULL; switch (type) { // simple cases - case x_short: + case x_int8: + { + sqlType = SQL_SMALLINT; + cType = SQL_C_STINYINT; + size = sizeof(int8_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); + prepare_indicators(v.size()); + sqlData = &v[0]; + } + break; + case x_uint8: + { + sqlType = SQL_SMALLINT; + cType = SQL_C_UTINYINT; + size = sizeof(uint8_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); + prepare_indicators(v.size()); + sqlData = &v[0]; + } + break; + case x_int16: { sqlType = SQL_SMALLINT; cType = SQL_C_SSHORT; - size = sizeof(short); - std::vector *vp = static_cast *>(data); - std::vector &v(*vp); + size = sizeof(int16_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); + prepare_indicators(v.size()); + sqlData = &v[0]; + } + break; + case x_uint16: + { + sqlType = SQL_SMALLINT; + cType = SQL_C_USHORT; + size = sizeof(uint16_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); prepare_indicators(v.size()); sqlData = &v[0]; } break; - case x_integer: + case x_int32: { sqlType = SQL_INTEGER; cType = SQL_C_SLONG; - size = sizeof(int); - std::vector *vp = static_cast *>(data); - std::vector &v(*vp); + size = sizeof(int32_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); + prepare_indicators(v.size()); + sqlData = &v[0]; + } + break; + case x_uint32: + { + sqlType = SQL_INTEGER; + cType = SQL_C_ULONG; + size = sizeof(uint32_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); prepare_indicators(v.size()); sqlData = &v[0]; } break; - case x_long_long: + case x_int64: { sqlType = SQL_BIGINT; cType = SQL_C_SBIGINT; - size = sizeof(long long); - std::vector *vp - = static_cast *>(data); - std::vector &v(*vp); + size = sizeof(int64_t); + std::vector *vp + = static_cast *>(data); + std::vector &v(*vp); prepare_indicators(v.size()); sqlData = &v[0]; } break; - case x_unsigned_long_long: + case x_uint64: { sqlType = SQL_BIGINT; cType = SQL_C_UBIGINT; - size = sizeof(unsigned long long); - std::vector *vp - = static_cast *>(data); - std::vector &v(*vp); + size = sizeof(uint64_t); + std::vector *vp + = static_cast *>(data); + std::vector &v(*vp); prepare_indicators(v.size()); sqlData = &v[0]; } @@ -332,29 +377,53 @@ std::size_t db2_vector_use_type_backend::size() sz = vp->size(); } break; - case x_short: + case x_int8: + { + std::vector *vp = static_cast *>(data); + sz = vp->size(); + } + break; + case x_uint8: + { + std::vector *vp = static_cast *>(data); + sz = vp->size(); + } + break; + case x_int16: + { + std::vector *vp = static_cast *>(data); + sz = vp->size(); + } + break; + case x_uint16: + { + std::vector *vp = static_cast *>(data); + sz = vp->size(); + } + break; + case x_int32: { - std::vector *vp = static_cast *>(data); + std::vector *vp = static_cast *>(data); sz = vp->size(); } break; - case x_integer: + case x_uint32: { - std::vector *vp = static_cast *>(data); + std::vector *vp = static_cast *>(data); sz = vp->size(); } break; - case x_long_long: + case x_int64: { - std::vector *vp - = static_cast *>(data); + std::vector *vp + = static_cast *>(data); sz = vp->size(); } break; - case x_unsigned_long_long: + case x_uint64: { - std::vector *vp - = static_cast *>(data); + std::vector *vp + = static_cast *>(data); sz = vp->size(); } break; From e0d0038e9fce6e28e91f59f590d6e184f1b64e87 Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Tue, 5 Apr 2022 23:11:07 +0200 Subject: [PATCH 07/46] Update Firebird backend for complete integer type support --- include/private/firebird/common.h | 19 +++++---- src/backends/firebird/common.cpp | 12 +++--- src/backends/firebird/standard-into-type.cpp | 29 +++++++++---- src/backends/firebird/standard-use-type.cpp | 28 +++++++++---- src/backends/firebird/statement.cpp | 16 ++++++- src/backends/firebird/vector-into-type.cpp | 40 ++++++++++++++---- src/backends/firebird/vector-use-type.cpp | 44 ++++++++++++++------ 7 files changed, 134 insertions(+), 54 deletions(-) diff --git a/include/private/firebird/common.h b/include/private/firebird/common.h index 94468bfd1..6e07ce45e 100644 --- a/include/private/firebird/common.h +++ b/include/private/firebird/common.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -135,20 +136,20 @@ void to_isc(void * val, XSQLVAR * var, short x_scale = 0) { case SQL_SHORT: { - short tmp = static_cast(round_for_isc(value*multiplier)/divisor); - std::memcpy(var->sqldata, &tmp, sizeof(short)); + int16_t tmp = static_cast(round_for_isc(value*multiplier)/divisor); + std::memcpy(var->sqldata, &tmp, sizeof(int16_t)); } break; case SQL_LONG: { - int tmp = static_cast(round_for_isc(value*multiplier)/divisor); - std::memcpy(var->sqldata, &tmp, sizeof(int)); + int32_t tmp = static_cast(round_for_isc(value*multiplier)/divisor); + std::memcpy(var->sqldata, &tmp, sizeof(int32_t)); } break; case SQL_INT64: { - long long tmp = static_cast(round_for_isc(value*multiplier)/divisor); - std::memcpy(var->sqldata, &tmp, sizeof(long long)); + int64_t tmp = static_cast(round_for_isc(value*multiplier)/divisor); + std::memcpy(var->sqldata, &tmp, sizeof(int64_t)); } break; case SQL_FLOAT: @@ -240,11 +241,11 @@ T1 from_isc(XSQLVAR * var) switch (var->sqltype & ~1) { case SQL_SHORT: - return static_cast(*reinterpret_cast(var->sqldata)/tens); + return static_cast(*reinterpret_cast(var->sqldata)/tens); case SQL_LONG: - return static_cast(*reinterpret_cast(var->sqldata)/tens); + return static_cast(*reinterpret_cast(var->sqldata)/tens); case SQL_INT64: - return static_cast(*reinterpret_cast(var->sqldata)/tens); + return static_cast(*reinterpret_cast(var->sqldata)/tens); case SQL_FLOAT: return static_cast(*reinterpret_cast(var->sqldata)); case SQL_DOUBLE: diff --git a/src/backends/firebird/common.cpp b/src/backends/firebird/common.cpp index 3e8580ebe..9b2b07852 100644 --- a/src/backends/firebird/common.cpp +++ b/src/backends/firebird/common.cpp @@ -123,15 +123,15 @@ void setTextParam(char const * s, std::size_t size, char * buf_, } else if (sqltype == SQL_SHORT) { - parse_decimal(buf_, var, s); + parse_decimal(buf_, var, s); } else if (sqltype == SQL_LONG) { - parse_decimal(buf_, var, s); + parse_decimal(buf_, var, s); } else if (sqltype == SQL_INT64) { - parse_decimal(buf_, var, s); + parse_decimal(buf_, var, s); } else if (sqltype == SQL_TIMESTAMP || sqltype == SQL_TYPE_DATE) @@ -204,15 +204,15 @@ std::string getTextParam(XSQLVAR const *var) } else if ((var->sqltype & ~1) == SQL_SHORT) { - return format_decimal(var->sqldata, var->sqlscale); + return format_decimal(var->sqldata, var->sqlscale); } else if ((var->sqltype & ~1) == SQL_LONG) { - return format_decimal(var->sqldata, var->sqlscale); + return format_decimal(var->sqldata, var->sqlscale); } else if ((var->sqltype & ~1) == SQL_INT64) { - return format_decimal(var->sqldata, var->sqlscale); + return format_decimal(var->sqldata, var->sqlscale); } else throw soci_error("Unexpected string type"); diff --git a/src/backends/firebird/standard-into-type.cpp b/src/backends/firebird/standard-into-type.cpp index 278b23fe1..796220eee 100644 --- a/src/backends/firebird/standard-into-type.cpp +++ b/src/backends/firebird/standard-into-type.cpp @@ -76,18 +76,29 @@ void firebird_standard_into_type_backend::exchangeData() case x_char: exchange_type_cast(data_) = getTextParam(var)[0]; break; - case x_short: - exchange_type_cast(data_) = from_isc(var); + case x_int8: + exchange_type_cast(data_) = from_isc(var); break; - case x_integer: - exchange_type_cast(data_) = from_isc(var); + case x_uint8: + exchange_type_cast(data_) = from_isc(var); break; - case x_long_long: - exchange_type_cast(data_) = from_isc(var); + case x_int16: + exchange_type_cast(data_) = from_isc(var); break; - case x_unsigned_long_long: - exchange_type_cast(data_) = - from_isc(var); + case x_uint16: + exchange_type_cast(data_) = from_isc(var); + break; + case x_int32: + exchange_type_cast(data_) = from_isc(var); + break; + case x_uint32: + exchange_type_cast(data_) = from_isc(var); + break; + case x_int64: + exchange_type_cast(data_) = from_isc(var); + break; + case x_uint64: + exchange_type_cast(data_) = from_isc(var); break; case x_double: exchange_type_cast(data_) = from_isc(var); diff --git a/src/backends/firebird/standard-use-type.cpp b/src/backends/firebird/standard-use-type.cpp index a1fa005e2..254c42d7e 100644 --- a/src/backends/firebird/standard-use-type.cpp +++ b/src/backends/firebird/standard-use-type.cpp @@ -107,17 +107,29 @@ void firebird_standard_use_type_backend::exchangeData() case x_char: setTextParam(&exchange_type_cast(data_), 1, buf_, var); break; - case x_short: - to_isc(data_, var); + case x_int8: + to_isc(data_, var); break; - case x_integer: - to_isc(data_, var); + case x_uint8: + to_isc(data_, var); break; - case x_long_long: - to_isc(data_, var); + case x_int16: + to_isc(data_, var); break; - case x_unsigned_long_long: - to_isc(data_, var); + case x_uint16: + to_isc(data_, var); + break; + case x_int32: + to_isc(data_, var); + break; + case x_uint32: + to_isc(data_, var); + break; + case x_int64: + to_isc(data_, var); + break; + case x_uint64: + to_isc(data_, var); break; case x_double: to_isc(data_, var); diff --git a/src/backends/firebird/statement.cpp b/src/backends/firebird/statement.cpp index f7ee8c947..fc5e59f4c 100644 --- a/src/backends/firebird/statement.cpp +++ b/src/backends/firebird/statement.cpp @@ -680,6 +680,18 @@ void firebird_statement_backend::describe_column(int colNum, type = dt_double; break; case SQL_SHORT: + if (var->sqlscale < 0) + { + if (session_.get_option_decimals_as_strings()) + type = dt_string; + else + type = dt_double; + } + else + { + type = dt_int16; + } + break; case SQL_LONG: if (var->sqlscale < 0) { @@ -690,7 +702,7 @@ void firebird_statement_backend::describe_column(int colNum, } else { - type = dt_integer; + type = dt_int32; } break; case SQL_INT64: @@ -703,7 +715,7 @@ void firebird_statement_backend::describe_column(int colNum, } else { - type = dt_long_long; + type = dt_int64; } break; /* case SQL_BLOB: diff --git a/src/backends/firebird/vector-into-type.cpp b/src/backends/firebird/vector-into-type.cpp index cbc721de4..50ec382a8 100644 --- a/src/backends/firebird/vector-into-type.cpp +++ b/src/backends/firebird/vector-into-type.cpp @@ -63,27 +63,51 @@ void firebird_vector_into_type_backend::exchangeData(std::size_t row) case x_char: setIntoVector(data_, row, getTextParam(var)[0]); break; - case x_short: + case x_int8: { - short tmp = from_isc(var); + int8_t tmp = from_isc(var); setIntoVector(data_, row, tmp); } break; - case x_integer: + case x_uint8: { - int tmp = from_isc(var); + uint8_t tmp = from_isc(var); setIntoVector(data_, row, tmp); } break; - case x_long_long: + case x_int16: { - long long tmp = from_isc(var); + int16_t tmp = from_isc(var); setIntoVector(data_, row, tmp); } break; - case x_unsigned_long_long: + case x_uint16: { - unsigned long long tmp = from_isc(var); + uint16_t tmp = from_isc(var); + setIntoVector(data_, row, tmp); + } + break; + case x_int32: + { + int32_t tmp = from_isc(var); + setIntoVector(data_, row, tmp); + } + break; + case x_uint32: + { + uint32_t tmp = from_isc(var); + setIntoVector(data_, row, tmp); + } + break; + case x_int64: + { + int64_t tmp = from_isc(var); + setIntoVector(data_, row, tmp); + } + break; + case x_uint64: + { + uint64_t tmp = from_isc(var); setIntoVector(data_, row, tmp); } break; diff --git a/src/backends/firebird/vector-use-type.cpp b/src/backends/firebird/vector-use-type.cpp index 13404ac24..0635a54dc 100644 --- a/src/backends/firebird/vector-use-type.cpp +++ b/src/backends/firebird/vector-use-type.cpp @@ -119,24 +119,44 @@ void firebird_vector_use_type_backend::exchangeData(std::size_t row) case x_char: setTextParam(getUseVectorValue(data_, row), 1, buf_, var); break; - case x_short: - to_isc( - static_cast(getUseVectorValue(data_, row)), + case x_int8: + to_isc( + static_cast(getUseVectorValue(data_, row)), var); break; - case x_integer: - to_isc( - static_cast(getUseVectorValue(data_, row)), + case x_uint8: + to_isc( + static_cast(getUseVectorValue(data_, row)), var); break; - case x_long_long: - to_isc( - static_cast(getUseVectorValue(data_, row)), + case x_int16: + to_isc( + static_cast(getUseVectorValue(data_, row)), var); break; - case x_unsigned_long_long: - to_isc( - static_cast(getUseVectorValue(data_, row)), + case x_uint16: + to_isc( + static_cast(getUseVectorValue(data_, row)), + var); + break; + case x_int32: + to_isc( + static_cast(getUseVectorValue(data_, row)), + var); + break; + case x_uint32: + to_isc( + static_cast(getUseVectorValue(data_, row)), + var); + break; + case x_int64: + to_isc( + static_cast(getUseVectorValue(data_, row)), + var); + break; + case x_uint64: + to_isc( + static_cast(getUseVectorValue(data_, row)), var); break; case x_double: From 6aa6aa7715c77c05705b6313df02e97452e84e5d Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Tue, 5 Apr 2022 23:11:28 +0200 Subject: [PATCH 08/46] Update ODBC backend for complete integer type support --- src/backends/odbc/standard-into-type.cpp | 41 +++++--- src/backends/odbc/standard-use-type.cpp | 41 ++++++-- src/backends/odbc/statement.cpp | 19 +++- src/backends/odbc/vector-into-type.cpp | 77 ++++++++++----- src/backends/odbc/vector-use-type.cpp | 113 ++++++++++++++++------- 5 files changed, 212 insertions(+), 79 deletions(-) diff --git a/src/backends/odbc/standard-into-type.cpp b/src/backends/odbc/standard-into-type.cpp index 26a4b41be..d856549b3 100644 --- a/src/backends/odbc/standard-into-type.cpp +++ b/src/backends/odbc/standard-into-type.cpp @@ -13,6 +13,7 @@ #include "soci-exchange-cast.h" #include "soci-mktime.h" #include +#include using namespace soci; using namespace soci::details; @@ -49,15 +50,31 @@ void odbc_standard_into_type_backend::define_by_pos( buf_ = new char[size]; data = buf_; break; - case x_short: + case x_int8: + odbcType_ = SQL_C_STINYINT; + size = sizeof(int8_t); + break; + case x_uint8: + odbcType_ = SQL_C_UTINYINT; + size = sizeof(uint8_t); + break; + case x_int16: odbcType_ = SQL_C_SSHORT; - size = sizeof(short); + size = sizeof(int16_t); + break; + case x_uint16: + odbcType_ = SQL_C_USHORT; + size = sizeof(uint16_t); break; - case x_integer: + case x_int32: odbcType_ = SQL_C_SLONG; - size = sizeof(int); + size = sizeof(int32_t); + break; + case x_uint32: + odbcType_ = SQL_C_ULONG; + size = sizeof(uint32_t); break; - case x_long_long: + case x_int64: if (use_string_for_bigint()) { odbcType_ = SQL_C_CHAR; @@ -68,10 +85,10 @@ void odbc_standard_into_type_backend::define_by_pos( else // Normal case, use ODBC support. { odbcType_ = SQL_C_SBIGINT; - size = sizeof(long long); + size = sizeof(int64_t); } break; - case x_unsigned_long_long: + case x_uint64: if (use_string_for_bigint()) { odbcType_ = SQL_C_CHAR; @@ -82,7 +99,7 @@ void odbc_standard_into_type_backend::define_by_pos( else // Normal case, use ODBC support. { odbcType_ = SQL_C_UBIGINT; - size = sizeof(unsigned long long); + size = sizeof(uint64_t); } break; case x_double: @@ -191,17 +208,17 @@ void odbc_standard_into_type_backend::post_fetch( ts->year, ts->month, ts->day, ts->hour, ts->minute, ts->second); } - else if (type_ == x_long_long && use_string_for_bigint()) + else if (type_ == x_int64 && use_string_for_bigint()) { - long long& ll = exchange_type_cast(data_); + int64_t ll = exchange_type_cast(data_); if (!cstring_to_integer(ll, buf_)) { throw soci_error("Failed to parse the returned 64-bit integer value"); } } - else if (type_ == x_unsigned_long_long && use_string_for_bigint()) + else if (type_ == x_uint64 && use_string_for_bigint()) { - unsigned long long& ll = exchange_type_cast(data_); + uint64_t ll = exchange_type_cast(data_); if (!cstring_to_unsigned(ll, buf_)) { throw soci_error("Failed to parse the returned 64-bit integer value"); diff --git a/src/backends/odbc/standard-use-type.cpp b/src/backends/odbc/standard-use-type.cpp index 60ec149e7..204b66944 100644 --- a/src/backends/odbc/standard-use-type.cpp +++ b/src/backends/odbc/standard-use-type.cpp @@ -13,6 +13,7 @@ #include #include #include +#include using namespace soci; using namespace soci::details; @@ -23,17 +24,37 @@ void* odbc_standard_use_type_backend::prepare_for_bind( switch (type_) { // simple cases - case x_short: + case x_int8: + sqlType = SQL_TINYINT; + cType = SQL_C_STINYINT; + size = sizeof(int8_t); + break; + case x_uint8: + sqlType = SQL_TINYINT; + cType = SQL_C_UTINYINT; + size = sizeof(uint8_t); + break; + case x_int16: sqlType = SQL_SMALLINT; cType = SQL_C_SSHORT; - size = sizeof(short); + size = sizeof(int16_t); + break; + case x_uint16: + sqlType = SQL_SMALLINT; + cType = SQL_C_USHORT; + size = sizeof(uint16_t); break; - case x_integer: + case x_int32: sqlType = SQL_INTEGER; cType = SQL_C_SLONG; - size = sizeof(int); + size = sizeof(int32_t); + break; + case x_uint32: + sqlType = SQL_INTEGER; + cType = SQL_C_ULONG; + size = sizeof(uint32_t); break; - case x_long_long: + case x_int64: if (use_string_for_bigint()) { sqlType = SQL_NUMERIC; @@ -41,17 +62,17 @@ void* odbc_standard_use_type_backend::prepare_for_bind( size = max_bigint_length; buf_ = new char[size]; snprintf(buf_, size, "%" LL_FMT_FLAGS "d", - exchange_type_cast(data_)); + static_cast(exchange_type_cast(data_))); indHolder_ = SQL_NTS; } else // Normal case, use ODBC support. { sqlType = SQL_BIGINT; cType = SQL_C_SBIGINT; - size = sizeof(long long); + size = sizeof(int64_t); } break; - case x_unsigned_long_long: + case x_uint64: if (use_string_for_bigint()) { sqlType = SQL_NUMERIC; @@ -59,14 +80,14 @@ void* odbc_standard_use_type_backend::prepare_for_bind( size = max_bigint_length; buf_ = new char[size]; snprintf(buf_, size, "%" LL_FMT_FLAGS "u", - exchange_type_cast(data_)); + static_cast(exchange_type_cast(data_))); indHolder_ = SQL_NTS; } else // Normal case, use ODBC support. { sqlType = SQL_BIGINT; cType = SQL_C_UBIGINT; - size = sizeof(unsigned long long); + size = sizeof(uint64_t); } break; case x_double: diff --git a/src/backends/odbc/statement.cpp b/src/backends/odbc/statement.cpp index 54711a5ed..b7bf888da 100644 --- a/src/backends/odbc/statement.cpp +++ b/src/backends/odbc/statement.cpp @@ -352,6 +352,17 @@ void odbc_statement_backend::describe_column(int colNum, data_type & type, char const *name = reinterpret_cast(colNameBuffer); columnName.assign(name, std::strlen(name)); + SQLLEN is_unsigned = 0; + SQLRETURN rc_colattr = SQLColAttribute(hstmt_, static_cast(colNum), + SQL_DESC_UNSIGNED, 0, 0, 0, &is_unsigned); + + if (is_odbc_error(rc_colattr)) + { + std::ostringstream ss; + ss << "getting col attribute of column at position " << colNum; + throw odbc_soci_error(SQL_HANDLE_STMT, hstmt_, ss.str()); + } + switch (dataType) { case SQL_TYPE_DATE: @@ -367,12 +378,16 @@ void odbc_statement_backend::describe_column(int colNum, data_type & type, type = dt_double; break; case SQL_TINYINT: + type = is_unsigned == SQL_TRUE ? dt_uint8 : dt_int8; + break; case SQL_SMALLINT: + type = is_unsigned == SQL_TRUE ? dt_uint16 : dt_int16; + break; case SQL_INTEGER: - type = dt_integer; + type = is_unsigned == SQL_TRUE ? dt_uint32 : dt_int32; break; case SQL_BIGINT: - type = dt_long_long; + type = is_unsigned == SQL_TRUE ? dt_uint64 : dt_int64; break; case SQL_CHAR: case SQL_VARCHAR: diff --git a/src/backends/odbc/vector-into-type.cpp b/src/backends/odbc/vector-into-type.cpp index 84863542a..28d379c3c 100644 --- a/src/backends/odbc/vector-into-type.cpp +++ b/src/backends/odbc/vector-into-type.cpp @@ -19,6 +19,7 @@ #include #include #include +#include using namespace soci; using namespace soci::details; @@ -43,14 +44,26 @@ void odbc_vector_into_type_backend::define_by_pos( switch (type) { // simple cases - case x_short: + case x_int8: + odbcType_ = SQL_C_STINYINT; + break; + case x_uint8: + odbcType_ = SQL_C_UTINYINT; + break; + case x_int16: odbcType_ = SQL_C_SSHORT; break; - case x_integer: + case x_uint16: + odbcType_ = SQL_C_USHORT; + break; + case x_int32: odbcType_ = SQL_C_SLONG; - static_assert(sizeof(SQLINTEGER) == sizeof(int), "unsupported SQLINTEGER size"); + static_assert(sizeof(SQLINTEGER) == sizeof(int32_t), "unsupported SQLINTEGER size"); break; - case x_long_long: + case x_uint32: + odbcType_ = SQL_C_ULONG; + break; + case x_int64: if (use_string_for_bigint()) { odbcType_ = SQL_C_CHAR; @@ -62,7 +75,7 @@ void odbc_vector_into_type_backend::define_by_pos( odbcType_ = SQL_C_SBIGINT; } break; - case x_unsigned_long_long: + case x_uint64: if (use_string_for_bigint()) { odbcType_ = SQL_C_CHAR; @@ -136,26 +149,42 @@ void odbc_vector_into_type_backend::rebind_row(std::size_t rowInd) switch (type_) { // simple cases - case x_short: - elementPtr = &exchange_vector_type_cast(data_)[rowInd]; - size = sizeof(short); + case x_int8: + elementPtr = &exchange_vector_type_cast(data_)[rowInd]; + size = sizeof(int8_t); + break; + case x_uint8: + elementPtr = &exchange_vector_type_cast(data_)[rowInd]; + size = sizeof(uint8_t); + break; + case x_int16: + elementPtr = &exchange_vector_type_cast(data_)[rowInd]; + size = sizeof(int16_t); + break; + case x_uint16: + elementPtr = &exchange_vector_type_cast(data_)[rowInd]; + size = sizeof(uint16_t); + break; + case x_int32: + elementPtr = &exchange_vector_type_cast(data_)[rowInd]; + size = sizeof(SQLINTEGER); break; - case x_integer: - elementPtr = &exchange_vector_type_cast(data_)[rowInd]; + case x_uint32: + elementPtr = &exchange_vector_type_cast(data_)[rowInd]; size = sizeof(SQLINTEGER); break; - case x_long_long: + case x_int64: if (!use_string_for_bigint()) { - elementPtr = &exchange_vector_type_cast(data_)[rowInd]; - size = sizeof(long long); + elementPtr = &exchange_vector_type_cast(data_)[rowInd]; + size = sizeof(int64_t); } break; - case x_unsigned_long_long: + case x_uint64: if (!use_string_for_bigint()) { - elementPtr = &exchange_vector_type_cast(data_)[rowInd]; - size = sizeof(unsigned long long); + elementPtr = &exchange_vector_type_cast(data_)[rowInd]; + size = sizeof(uint64_t); } break; case x_double: @@ -280,11 +309,11 @@ void odbc_vector_into_type_backend::do_post_fetch_rows( pos += colSize_; } } - else if (type_ == x_long_long && use_string_for_bigint()) + else if (type_ == x_int64 && use_string_for_bigint()) { - std::vector *vp - = static_cast *>(data_); - std::vector &v(*vp); + std::vector *vp + = static_cast *>(data_); + std::vector &v(*vp); char *pos = buf_; for (std::size_t i = beginRow; i != endRow; ++i) { @@ -295,11 +324,11 @@ void odbc_vector_into_type_backend::do_post_fetch_rows( pos += colSize_; } } - else if (type_ == x_unsigned_long_long && use_string_for_bigint()) + else if (type_ == x_uint64 && use_string_for_bigint()) { - std::vector *vp - = static_cast *>(data_); - std::vector &v(*vp); + std::vector *vp + = static_cast *>(data_); + std::vector &v(*vp); char *pos = buf_; for (std::size_t i = beginRow; i != endRow; ++i) { diff --git a/src/backends/odbc/vector-use-type.cpp b/src/backends/odbc/vector-use-type.cpp index 90ab74e54..45b845f6e 100644 --- a/src/backends/odbc/vector-use-type.cpp +++ b/src/backends/odbc/vector-use-type.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #ifdef _MSC_VER // disables the warning about converting int to void*. This is a 64 bit compatibility @@ -42,34 +43,78 @@ void* odbc_vector_use_type_backend::prepare_for_bind(SQLUINTEGER &size, void* data = NULL; switch (type_) { // simple cases - case x_short: + case x_int8: + { + sqlType = SQL_TINYINT; + cType = SQL_C_STINYINT; + size = sizeof(int8_t); + std::vector *vp = static_cast *>(data_); + std::vector &v(*vp); + prepare_indicators(v.size()); + data = &v[0]; + } + break; + case x_uint8: + { + sqlType = SQL_TINYINT; + cType = SQL_C_UTINYINT; + size = sizeof(uint8_t); + std::vector *vp = static_cast *>(data_); + std::vector &v(*vp); + prepare_indicators(v.size()); + data = &v[0]; + } + break; + case x_int16: { sqlType = SQL_SMALLINT; cType = SQL_C_SSHORT; - size = sizeof(short); - std::vector *vp = static_cast *>(data_); - std::vector &v(*vp); + size = sizeof(int16_t); + std::vector *vp = static_cast *>(data_); + std::vector &v(*vp); + prepare_indicators(v.size()); + data = &v[0]; + } + break; + case x_uint16: + { + sqlType = SQL_SMALLINT; + cType = SQL_C_USHORT; + size = sizeof(uint16_t); + std::vector *vp = static_cast *>(data_); + std::vector &v(*vp); prepare_indicators(v.size()); data = &v[0]; } break; - case x_integer: + case x_int32: { sqlType = SQL_INTEGER; cType = SQL_C_SLONG; size = sizeof(SQLINTEGER); - static_assert(sizeof(SQLINTEGER) == sizeof(int), "unsupported SQLINTEGER size"); - std::vector *vp = static_cast *>(data_); - std::vector &v(*vp); + static_assert(sizeof(SQLINTEGER) == sizeof(int32_t), "unsupported SQLINTEGER size"); + std::vector *vp = static_cast *>(data_); + std::vector &v(*vp); + prepare_indicators(v.size()); + data = &v[0]; + } + break; + case x_uint32: + { + sqlType = SQL_INTEGER; + cType = SQL_C_ULONG; + size = sizeof(SQLINTEGER); + std::vector *vp = static_cast *>(data_); + std::vector &v(*vp); prepare_indicators(v.size()); data = &v[0]; } break; - case x_long_long: + case x_int64: { - std::vector *vp = - static_cast *>(data_); - std::vector &v(*vp); + std::vector *vp = + static_cast *>(data_); + std::vector &v(*vp); std::size_t const vsize = v.size(); prepare_indicators(vsize); @@ -85,16 +130,16 @@ void* odbc_vector_use_type_backend::prepare_for_bind(SQLUINTEGER &size, { sqlType = SQL_BIGINT; cType = SQL_C_SBIGINT; - size = sizeof(long long); + size = sizeof(int64_t); data = &v[0]; } } break; - case x_unsigned_long_long: + case x_uint64: { - std::vector *vp = - static_cast *>(data_); - std::vector &v(*vp); + std::vector *vp = + static_cast *>(data_); + std::vector &v(*vp); std::size_t const vsize = v.size(); prepare_indicators(vsize); @@ -109,8 +154,8 @@ void* odbc_vector_use_type_backend::prepare_for_bind(SQLUINTEGER &size, else // Normal case, use ODBC support. { sqlType = SQL_BIGINT; - cType = SQL_C_SBIGINT; - size = sizeof(unsigned long long); + cType = SQL_C_UBIGINT; + size = sizeof(uint64_t); data = &v[0]; } } @@ -282,8 +327,12 @@ void odbc_vector_use_type_backend::pre_use(indicator const *ind) SQLLEN non_null_indicator = 0; switch (type_) { - case x_short: - case x_integer: + case x_int8: + case x_uint8: + case x_int16: + case x_uint16: + case x_int32: + case x_uint32: case x_double: // Length of the parameter value is ignored for these types. break; @@ -327,18 +376,19 @@ void odbc_vector_use_type_backend::pre_use(indicator const *ind) } break; - case x_long_long: + case x_int64: if (use_string_for_bigint()) { - std::vector *vp - = static_cast *>(data_); - std::vector &v(*vp); + std::vector *vp + = static_cast *>(data_); + std::vector &v(*vp); char *pos = buf_; std::size_t const vsize = v.size(); for (std::size_t i = 0; i != vsize; ++i) { - snprintf(pos, max_bigint_length, "%" LL_FMT_FLAGS "d", v[i]); + snprintf(pos, max_bigint_length, "%" LL_FMT_FLAGS "d", + static_cast(v[i])); pos += max_bigint_length; } @@ -346,18 +396,19 @@ void odbc_vector_use_type_backend::pre_use(indicator const *ind) } break; - case x_unsigned_long_long: + case x_uint64: if (use_string_for_bigint()) { - std::vector *vp - = static_cast *>(data_); - std::vector &v(*vp); + std::vector *vp + = static_cast *>(data_); + std::vector &v(*vp); char *pos = buf_; std::size_t const vsize = v.size(); for (std::size_t i = 0; i != vsize; ++i) { - snprintf(pos, max_bigint_length, "%" LL_FMT_FLAGS "u", v[i]); + snprintf(pos, max_bigint_length, "%" LL_FMT_FLAGS "u", + static_cast(v[i])); pos += max_bigint_length; } From ca28449ba5aa8da0994447a4fbf48494b95d24ae Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Tue, 5 Apr 2022 23:38:36 +0200 Subject: [PATCH 09/46] Update soci-simple for complete integer type support --- include/soci/soci-simple.h | 168 ++-- src/core/soci-simple.cpp | 1708 +++++++++++++++++++++++++++++++----- 2 files changed, 1609 insertions(+), 267 deletions(-) diff --git a/include/soci/soci-simple.h b/include/soci/soci-simple.h index 5771c44eb..785d2f7db 100644 --- a/include/soci/soci-simple.h +++ b/include/soci/soci-simple.h @@ -10,6 +10,8 @@ #include "soci/soci-platform.h" +#include + #ifdef __cplusplus extern "C" { @@ -56,66 +58,108 @@ 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_double (statement_handle st); -SOCI_DECL int soci_into_date (statement_handle st); -SOCI_DECL int soci_into_blob (statement_handle st); +SOCI_DECL int soci_into_string(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_double_v (statement_handle st); -SOCI_DECL int soci_into_date_v (statement_handle st); +SOCI_DECL int soci_into_string_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 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); +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 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 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); +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 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_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); +SOCI_DECL void soci_use_string(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_double_v (statement_handle st, char const * name); -SOCI_DECL void soci_use_date_v (statement_handle st, char const * name); +SOCI_DECL void soci_use_string_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_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); +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_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); @@ -126,10 +170,22 @@ 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, @@ -137,13 +193,19 @@ SOCI_DECL void soci_set_use_date_v(statement_handle st, // 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 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); +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 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 diff --git a/src/core/soci-simple.cpp b/src/core/soci-simple.cpp index 80b6d579d..be7820909 100644 --- a/src/core/soci-simple.cpp +++ b/src/core/soci-simple.cpp @@ -356,32 +356,56 @@ struct statement_wrapper std::vector into_types; // for both single and bulk std::vector into_indicators; std::map into_strings; - std::map into_ints; - std::map into_longlongs; + std::map into_int8; + std::map into_uint8; + std::map into_int16; + std::map into_uint16; + std::map into_int32; + std::map into_uint32; + std::map into_int64; + std::map into_uint64; std::map into_doubles; std::map into_dates; std::map into_blob; std::vector > into_indicators_v; std::map > into_strings_v; - std::map > into_ints_v; - std::map > into_longlongs_v; + std::map > into_int8_v; + std::map > into_uint8_v; + std::map > into_int16_v; + std::map > into_uint16_v; + std::map > into_int32_v; + std::map > into_uint32_v; + std::map > into_int64_v; + std::map > into_uint64_v; std::map > into_doubles_v; std::map > into_dates_v; // use elements std::map use_indicators; std::map use_strings; - std::map use_ints; - std::map use_longlongs; + std::map use_int8; + std::map use_uint8; + std::map use_int16; + std::map use_uint16; + std::map use_int32; + std::map use_uint32; + std::map use_int64; + std::map use_uint64; std::map use_doubles; std::map use_dates; std::map use_blob; std::map > use_indicators_v; std::map > use_strings_v; - std::map > use_ints_v; - std::map > use_longlongs_v; + std::map > use_int8_v; + std::map > use_uint8_v; + std::map > use_int16_v; + std::map > use_uint16_v; + std::map > use_int32_v; + std::map > use_uint32_v; + std::map > use_int64_v; + std::map > use_uint64_v; std::map > use_doubles_v; std::map > use_dates_v; @@ -594,20 +618,62 @@ bool name_exists_check_failed(statement_wrapper & wrapper, name_exists = (it != wrapper.use_strings.end()); } break; - case dt_integer: + case dt_int8: { - typedef std::map::const_iterator iterator; - iterator const it = wrapper.use_ints.find(name); - name_exists = (it != wrapper.use_ints.end()); + typedef std::map::const_iterator iterator; + iterator const it = wrapper.use_int8.find(name); + name_exists = (it != wrapper.use_int8.end()); } break; - case dt_long_long: - case dt_unsigned_long_long: + case dt_uint8: { - typedef std::map::const_iterator + typedef std::map::const_iterator iterator; + iterator const it = wrapper.use_uint8.find(name); + name_exists = (it != wrapper.use_uint8.end()); + } + break; + case dt_int16: + { + typedef std::map::const_iterator iterator; + iterator const it = wrapper.use_int16.find(name); + name_exists = (it != wrapper.use_int16.end()); + } + break; + case dt_uint16: + { + typedef std::map::const_iterator iterator; + iterator const it = wrapper.use_uint16.find(name); + name_exists = (it != wrapper.use_uint16.end()); + } + break; + case dt_int32: + { + typedef std::map::const_iterator iterator; + iterator const it = wrapper.use_int32.find(name); + name_exists = (it != wrapper.use_int32.end()); + } + break; + case dt_uint32: + { + typedef std::map::const_iterator iterator; + iterator const it = wrapper.use_uint32.find(name); + name_exists = (it != wrapper.use_uint32.end()); + } + break; + case dt_int64: + { + typedef std::map::const_iterator + iterator; + iterator const it = wrapper.use_int64.find(name); + name_exists = (it != wrapper.use_int64.end()); + } + break; + case dt_uint64: + { + typedef std::map::const_iterator iterator; - iterator const it = wrapper.use_longlongs.find(name); - name_exists = (it != wrapper.use_longlongs.end()); + iterator const it = wrapper.use_uint64.find(name); + name_exists = (it != wrapper.use_uint64.end()); } break; case dt_double: @@ -652,27 +718,92 @@ bool name_exists_check_failed(statement_wrapper & wrapper, name_exists = (it != wrapper.use_strings_v.end()); } break; - case dt_integer: + case dt_int8: + { + typedef std::map + < + std::string, + std::vector + >::const_iterator iterator; + iterator const it = wrapper.use_int8_v.find(name); + name_exists = (it != wrapper.use_int8_v.end()); + } + break; + case dt_uint8: + { + typedef std::map + < + std::string, + std::vector + >::const_iterator iterator; + iterator const it = wrapper.use_uint8_v.find(name); + name_exists = (it != wrapper.use_uint8_v.end()); + } + break; + case dt_int16: + { + typedef std::map + < + std::string, + std::vector + >::const_iterator iterator; + iterator const it = wrapper.use_int16_v.find(name); + name_exists = (it != wrapper.use_int16_v.end()); + } + break; + case dt_uint16: + { + typedef std::map + < + std::string, + std::vector + >::const_iterator iterator; + iterator const it = wrapper.use_uint16_v.find(name); + name_exists = (it != wrapper.use_uint16_v.end()); + } + break; + case dt_int32: + { + typedef std::map + < + std::string, + std::vector + >::const_iterator iterator; + iterator const it = wrapper.use_int32_v.find(name); + name_exists = (it != wrapper.use_int32_v.end()); + } + break; + case dt_uint32: + { + typedef std::map + < + std::string, + std::vector + >::const_iterator iterator; + iterator const it = wrapper.use_uint32_v.find(name); + name_exists = (it != wrapper.use_uint32_v.end()); + } + break; + case dt_int64: { typedef std::map < std::string, - std::vector + std::vector >::const_iterator iterator; - iterator const it = wrapper.use_ints_v.find(name); - name_exists = (it != wrapper.use_ints_v.end()); + iterator const it = wrapper.use_int64_v.find(name); + name_exists = (it != wrapper.use_int64_v.end()); } break; - case dt_long_long: - case dt_unsigned_long_long: + case dt_uint64: { typedef std::map < std::string, - std::vector + std::vector >::const_iterator iterator; - iterator const it = wrapper.use_longlongs_v.find(name); - name_exists = (it != wrapper.use_longlongs_v.end()); + iterator const it = wrapper.use_uint64_v.find(name); + name_exists = (it != wrapper.use_uint64_v.end()); } break; case dt_double: @@ -811,7 +942,115 @@ SOCI_DECL int soci_into_string(statement_handle st) return wrapper->next_position++; } -SOCI_DECL int soci_into_int(statement_handle st) +SOCI_DECL int soci_into_int8(statement_handle st) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::single, true)) + { + return -1; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->into_kind = statement_wrapper::single; + + wrapper->into_types.push_back(dt_int8); + wrapper->into_indicators.push_back(i_ok); + wrapper->into_int8[wrapper->next_position]; // create new entry + return wrapper->next_position++; +} + +SOCI_DECL int soci_into_uint8(statement_handle st) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::single, true)) + { + return -1; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->into_kind = statement_wrapper::single; + + wrapper->into_types.push_back(dt_uint8); + wrapper->into_indicators.push_back(i_ok); + wrapper->into_uint8[wrapper->next_position]; // create new entry + return wrapper->next_position++; +} + +SOCI_DECL int soci_into_int16(statement_handle st) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::single, true)) + { + return -1; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->into_kind = statement_wrapper::single; + + wrapper->into_types.push_back(dt_int16); + wrapper->into_indicators.push_back(i_ok); + wrapper->into_int16[wrapper->next_position]; // create new entry + return wrapper->next_position++; +} + +SOCI_DECL int soci_into_uint16(statement_handle st) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::single, true)) + { + return -1; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->into_kind = statement_wrapper::single; + + wrapper->into_types.push_back(dt_uint16); + wrapper->into_indicators.push_back(i_ok); + wrapper->into_uint16[wrapper->next_position]; // create new entry + return wrapper->next_position++; +} + +SOCI_DECL int soci_into_int32(statement_handle st) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::single, true)) + { + return -1; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->into_kind = statement_wrapper::single; + + wrapper->into_types.push_back(dt_int32); + wrapper->into_indicators.push_back(i_ok); + wrapper->into_int32[wrapper->next_position]; // create new entry + return wrapper->next_position++; +} + +SOCI_DECL int soci_into_uint32(statement_handle st) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::single, true)) + { + return -1; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->into_kind = statement_wrapper::single; + + wrapper->into_types.push_back(dt_uint32); + wrapper->into_indicators.push_back(i_ok); + wrapper->into_uint32[wrapper->next_position]; // create new entry + return wrapper->next_position++; +} + +SOCI_DECL int soci_into_int64(statement_handle st) { statement_wrapper * wrapper = static_cast(st); @@ -823,13 +1062,13 @@ SOCI_DECL int soci_into_int(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::single; - wrapper->into_types.push_back(dt_integer); + wrapper->into_types.push_back(dt_int64); wrapper->into_indicators.push_back(i_ok); - wrapper->into_ints[wrapper->next_position]; // create new entry + wrapper->into_int64[wrapper->next_position]; // create new entry return wrapper->next_position++; } -SOCI_DECL int soci_into_long_long(statement_handle st) +SOCI_DECL int soci_into_uint64(statement_handle st) { statement_wrapper * wrapper = static_cast(st); @@ -841,9 +1080,9 @@ SOCI_DECL int soci_into_long_long(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::single; - wrapper->into_types.push_back(dt_long_long); + wrapper->into_types.push_back(dt_uint64); wrapper->into_indicators.push_back(i_ok); - wrapper->into_longlongs[wrapper->next_position]; // create new entry + wrapper->into_uint64[wrapper->next_position]; // create new entry return wrapper->next_position++; } @@ -919,7 +1158,115 @@ SOCI_DECL int soci_into_string_v(statement_handle st) return wrapper->next_position++; } -SOCI_DECL int soci_into_int_v(statement_handle st) +SOCI_DECL int soci_into_int8_v(statement_handle st) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, true)) + { + return -1; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->into_kind = statement_wrapper::bulk; + + wrapper->into_types.push_back(dt_int8); + wrapper->into_indicators_v.push_back(std::vector()); + wrapper->into_int8_v[wrapper->next_position]; + return wrapper->next_position++; +} + +SOCI_DECL int soci_into_uint8_v(statement_handle st) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, true)) + { + return -1; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->into_kind = statement_wrapper::bulk; + + wrapper->into_types.push_back(dt_uint8); + wrapper->into_indicators_v.push_back(std::vector()); + wrapper->into_uint8_v[wrapper->next_position]; + return wrapper->next_position++; +} + +SOCI_DECL int soci_into_int16_v(statement_handle st) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, true)) + { + return -1; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->into_kind = statement_wrapper::bulk; + + wrapper->into_types.push_back(dt_int16); + wrapper->into_indicators_v.push_back(std::vector()); + wrapper->into_int16_v[wrapper->next_position]; + return wrapper->next_position++; +} + +SOCI_DECL int soci_into_uint16_v(statement_handle st) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, true)) + { + return -1; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->into_kind = statement_wrapper::bulk; + + wrapper->into_types.push_back(dt_uint16); + wrapper->into_indicators_v.push_back(std::vector()); + wrapper->into_uint16_v[wrapper->next_position]; + return wrapper->next_position++; +} + +SOCI_DECL int soci_into_int32_v(statement_handle st) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, true)) + { + return -1; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->into_kind = statement_wrapper::bulk; + + wrapper->into_types.push_back(dt_int32); + wrapper->into_indicators_v.push_back(std::vector()); + wrapper->into_int32_v[wrapper->next_position]; + return wrapper->next_position++; +} + +SOCI_DECL int soci_into_uint32_v(statement_handle st) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, true)) + { + return -1; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->into_kind = statement_wrapper::bulk; + + wrapper->into_types.push_back(dt_uint32); + wrapper->into_indicators_v.push_back(std::vector()); + wrapper->into_uint32_v[wrapper->next_position]; + return wrapper->next_position++; +} + +SOCI_DECL int soci_into_int64_v(statement_handle st) { statement_wrapper * wrapper = static_cast(st); @@ -931,13 +1278,13 @@ SOCI_DECL int soci_into_int_v(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::bulk; - wrapper->into_types.push_back(dt_integer); + wrapper->into_types.push_back(dt_int64); wrapper->into_indicators_v.push_back(std::vector()); - wrapper->into_ints_v[wrapper->next_position]; + wrapper->into_int64_v[wrapper->next_position]; return wrapper->next_position++; } -SOCI_DECL int soci_into_long_long_v(statement_handle st) +SOCI_DECL int soci_into_uint64_v(statement_handle st) { statement_wrapper * wrapper = static_cast(st); @@ -949,9 +1296,9 @@ SOCI_DECL int soci_into_long_long_v(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::bulk; - wrapper->into_types.push_back(dt_long_long); + wrapper->into_types.push_back(dt_uint64); wrapper->into_indicators_v.push_back(std::vector()); - wrapper->into_longlongs_v[wrapper->next_position]; + wrapper->into_uint64_v[wrapper->next_position]; return wrapper->next_position++; } @@ -1020,65 +1367,149 @@ SOCI_DECL char const * soci_get_into_string(statement_handle st, int position) return wrapper->into_strings[position].c_str(); } -SOCI_DECL int soci_get_into_int(statement_handle st, int position) +SOCI_DECL int8_t soci_get_into_int8(statement_handle st, int position) { statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::single, position, dt_integer, "int") || + statement_wrapper::single, position, dt_int8, "int8") || not_null_check_failed(*wrapper, position)) { return 0; } - return wrapper->into_ints[position]; + return wrapper->into_int8[position]; } -SOCI_DECL long long soci_get_into_long_long(statement_handle st, int position) +SOCI_DECL uint8_t soci_get_into_uint8(statement_handle st, int position) { statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::single, position, dt_long_long, "long long") || + statement_wrapper::single, position, dt_uint8, "uint8") || not_null_check_failed(*wrapper, position)) { - return 0LL; + return 0; } - return wrapper->into_longlongs[position]; + return wrapper->into_uint8[position]; } -SOCI_DECL double soci_get_into_double(statement_handle st, int position) +SOCI_DECL int16_t soci_get_into_int16(statement_handle st, int position) { statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::single, position, dt_double, "double") || + statement_wrapper::single, position, dt_int16, "int16") || not_null_check_failed(*wrapper, position)) { - return 0.0; + return 0; } - return wrapper->into_doubles[position]; + return wrapper->into_int16[position]; } -SOCI_DECL char const * soci_get_into_date(statement_handle st, int position) +SOCI_DECL uint16_t soci_get_into_uint16(statement_handle st, int position) { statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::single, position, dt_date, "date") || + statement_wrapper::single, position, dt_uint16, "uint16") || not_null_check_failed(*wrapper, position)) { - return ""; + return 0; } - // format is: "YYYY MM DD hh mm ss" - std::tm const & d = wrapper->into_dates[position]; - return format_date(*wrapper, d); + return wrapper->into_uint16[position]; } -SOCI_DECL blob_handle soci_get_into_blob(statement_handle st, int position) +SOCI_DECL int32_t soci_get_into_int32(statement_handle st, int position) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::single, position, dt_int32, "int32") || + not_null_check_failed(*wrapper, position)) + { + return 0; + } + + return wrapper->into_int32[position]; +} + +SOCI_DECL uint32_t soci_get_into_uint32(statement_handle st, int position) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::single, position, dt_uint32, "uint32") || + not_null_check_failed(*wrapper, position)) + { + return 0; + } + + return wrapper->into_uint32[position]; +} + +SOCI_DECL int64_t soci_get_into_int64(statement_handle st, int position) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::single, position, dt_int64, "int64") || + not_null_check_failed(*wrapper, position)) + { + return 0LL; + } + + return wrapper->into_int64[position]; +} + +SOCI_DECL uint64_t soci_get_into_uint64(statement_handle st, int position) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::single, position, dt_uint64, "uint64") || + not_null_check_failed(*wrapper, position)) + { + return 0LL; + } + + return wrapper->into_uint64[position]; +} + +SOCI_DECL double soci_get_into_double(statement_handle st, int position) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::single, position, dt_double, "double") || + not_null_check_failed(*wrapper, position)) + { + return 0.0; + } + + return wrapper->into_doubles[position]; +} + +SOCI_DECL char const * soci_get_into_date(statement_handle st, int position) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::single, position, dt_date, "date") || + not_null_check_failed(*wrapper, position)) + { + return ""; + } + + // format is: "YYYY MM DD hh mm ss" + std::tm const & d = wrapper->into_dates[position]; + return format_date(*wrapper, d); +} + +SOCI_DECL blob_handle soci_get_into_blob(statement_handle st, int position) { statement_wrapper * wrapper = static_cast(st); @@ -1133,12 +1564,29 @@ SOCI_DECL void soci_into_resize_v(statement_handle st, int new_size) case dt_string: wrapper->into_strings_v[i].resize(new_size); break; - case dt_integer: - wrapper->into_ints_v[i].resize(new_size); + case dt_int8: + wrapper->into_int8_v[i].resize(new_size); + break; + case dt_uint8: + wrapper->into_uint8_v[i].resize(new_size); + break; + case dt_int16: + wrapper->into_int16_v[i].resize(new_size); + break; + case dt_uint16: + wrapper->into_uint16_v[i].resize(new_size); + break; + case dt_int32: + wrapper->into_int32_v[i].resize(new_size); + break; + case dt_uint32: + wrapper->into_uint32_v[i].resize(new_size); break; - case dt_long_long: - case dt_unsigned_long_long: - wrapper->into_longlongs_v[i].resize(new_size); + case dt_int64: + wrapper->into_int64_v[i].resize(new_size); + break; + case dt_uint64: + wrapper->into_uint64_v[i].resize(new_size); break; case dt_double: wrapper->into_doubles_v[i].resize(new_size); @@ -1196,17 +1644,137 @@ SOCI_DECL char const * soci_get_into_string_v(statement_handle st, int position, return v[index].c_str(); } -SOCI_DECL int soci_get_into_int_v(statement_handle st, int position, int index) +SOCI_DECL int8_t soci_get_into_int8_v(statement_handle st, int position, int index) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::bulk, position, dt_int8, "int8")) + { + return 0; + } + + std::vector const & v = wrapper->into_int8_v[position]; + if (index_check_failed(v, *wrapper, index) || + not_null_check_failed(*wrapper, position, index)) + { + return 0; + } + + return v[index]; +} + +SOCI_DECL uint8_t soci_get_into_uint8_v(statement_handle st, int position, int index) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::bulk, position, dt_uint8, "uint8")) + { + return 0; + } + + std::vector const & v = wrapper->into_uint8_v[position]; + if (index_check_failed(v, *wrapper, index) || + not_null_check_failed(*wrapper, position, index)) + { + return 0; + } + + return v[index]; +} + +SOCI_DECL int16_t soci_get_into_int16_v(statement_handle st, int position, int index) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::bulk, position, dt_int16, "int16")) + { + return 0; + } + + std::vector const & v = wrapper->into_int16_v[position]; + if (index_check_failed(v, *wrapper, index) || + not_null_check_failed(*wrapper, position, index)) + { + return 0; + } + + return v[index]; +} + +SOCI_DECL uint16_t soci_get_into_uint16_v(statement_handle st, int position, int index) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::bulk, position, dt_uint16, "uint16")) + { + return 0; + } + + std::vector const & v = wrapper->into_uint16_v[position]; + if (index_check_failed(v, *wrapper, index) || + not_null_check_failed(*wrapper, position, index)) + { + return 0; + } + + return v[index]; +} + +SOCI_DECL int32_t soci_get_into_int32_v(statement_handle st, int position, int index) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::bulk, position, dt_int32, "int32")) + { + return 0; + } + + std::vector const & v = wrapper->into_int32_v[position]; + if (index_check_failed(v, *wrapper, index) || + not_null_check_failed(*wrapper, position, index)) + { + return 0; + } + + return v[index]; +} + +SOCI_DECL uint32_t soci_get_into_uint32_v(statement_handle st, int position, int index) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::bulk, position, dt_uint32, "uint32")) + { + return 0; + } + + std::vector const & v = wrapper->into_uint32_v[position]; + if (index_check_failed(v, *wrapper, index) || + not_null_check_failed(*wrapper, position, index)) + { + return 0; + } + + return v[index]; +} + +SOCI_DECL int64_t soci_get_into_int64_v(statement_handle st, int position, int index) { statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::bulk, position, dt_integer, "int")) + statement_wrapper::bulk, position, dt_int64, "int64")) { return 0; } - std::vector const & v = wrapper->into_ints_v[position]; + std::vector const & v = wrapper->into_int64_v[position]; if (index_check_failed(v, *wrapper, index) || not_null_check_failed(*wrapper, position, index)) { @@ -1216,17 +1784,17 @@ SOCI_DECL int soci_get_into_int_v(statement_handle st, int position, int index) return v[index]; } -SOCI_DECL long long soci_get_into_long_long_v(statement_handle st, int position, int index) +SOCI_DECL uint64_t soci_get_into_uint64_v(statement_handle st, int position, int index) { statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::bulk, position, dt_long_long, "long long")) + statement_wrapper::bulk, position, dt_uint64, "uint64")) { return 0; } - std::vector const & v = wrapper->into_longlongs_v[position]; + std::vector const & v = wrapper->into_uint64_v[position]; if (index_check_failed(v, *wrapper, index) || not_null_check_failed(*wrapper, position, index)) { @@ -1293,7 +1861,7 @@ SOCI_DECL void soci_use_string(statement_handle st, char const * name) wrapper->use_strings[name]; // create new entry } -SOCI_DECL void soci_use_int(statement_handle st, char const * name) +SOCI_DECL void soci_use_int8(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); @@ -1307,10 +1875,10 @@ SOCI_DECL void soci_use_int(statement_handle st, char const * name) wrapper->use_kind = statement_wrapper::single; wrapper->use_indicators[name] = i_ok; // create new entry - wrapper->use_ints[name]; // create new entry + wrapper->use_int8[name]; // create new entry } -SOCI_DECL void soci_use_long_long(statement_handle st, char const * name) +SOCI_DECL void soci_use_uint8(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); @@ -1324,10 +1892,10 @@ SOCI_DECL void soci_use_long_long(statement_handle st, char const * name) wrapper->use_kind = statement_wrapper::single; wrapper->use_indicators[name] = i_ok; // create new entry - wrapper->use_longlongs[name]; // create new entry + wrapper->use_uint8[name]; // create new entry } -SOCI_DECL void soci_use_double(statement_handle st, char const * name) +SOCI_DECL void soci_use_int16(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); @@ -1341,10 +1909,10 @@ SOCI_DECL void soci_use_double(statement_handle st, char const * name) wrapper->use_kind = statement_wrapper::single; wrapper->use_indicators[name] = i_ok; // create new entry - wrapper->use_doubles[name]; // create new entry + wrapper->use_int16[name]; // create new entry } -SOCI_DECL void soci_use_date(statement_handle st, char const * name) +SOCI_DECL void soci_use_uint16(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); @@ -1358,10 +1926,10 @@ SOCI_DECL void soci_use_date(statement_handle st, char const * name) wrapper->use_kind = statement_wrapper::single; wrapper->use_indicators[name] = i_ok; // create new entry - wrapper->use_dates[name]; // create new entry + wrapper->use_uint16[name]; // create new entry } -SOCI_DECL void soci_use_blob(statement_handle st, char const * name) +SOCI_DECL void soci_use_int32(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); @@ -1374,113 +1942,317 @@ SOCI_DECL void soci_use_blob(statement_handle st, char const * name) wrapper->statement_state = statement_wrapper::defining; wrapper->use_kind = statement_wrapper::single; - wrapper->use_indicators[name] = i_null; // create new entry - wrapper->use_blob[name] = soci_create_blob_session(wrapper->sql); // create new entry + wrapper->use_indicators[name] = i_ok; // create new entry + wrapper->use_int32[name]; // create new entry } -SOCI_DECL void soci_use_string_v(statement_handle st, char const * name) +SOCI_DECL void soci_use_uint32(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); - if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) || - name_unique_check_failed(*wrapper, statement_wrapper::bulk, name)) + if (cannot_add_elements(*wrapper, statement_wrapper::single, false) || + name_unique_check_failed(*wrapper, statement_wrapper::single, name)) { return; } wrapper->statement_state = statement_wrapper::defining; - wrapper->use_kind = statement_wrapper::bulk; + wrapper->use_kind = statement_wrapper::single; - wrapper->use_indicators_v[name]; // create new entry - wrapper->use_strings_v[name]; // create new entry + wrapper->use_indicators[name] = i_ok; // create new entry + wrapper->use_uint32[name]; // create new entry } -SOCI_DECL void soci_use_int_v(statement_handle st, char const * name) +SOCI_DECL void soci_use_int64(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); - if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) || - name_unique_check_failed(*wrapper, statement_wrapper::bulk, name)) + if (cannot_add_elements(*wrapper, statement_wrapper::single, false) || + name_unique_check_failed(*wrapper, statement_wrapper::single, name)) { return; } wrapper->statement_state = statement_wrapper::defining; - wrapper->use_kind = statement_wrapper::bulk; + wrapper->use_kind = statement_wrapper::single; - wrapper->use_indicators_v[name]; // create new entry - wrapper->use_ints_v[name]; // create new entry + wrapper->use_indicators[name] = i_ok; // create new entry + wrapper->use_int64[name]; // create new entry } -SOCI_DECL void soci_use_long_long_v(statement_handle st, char const * name) +SOCI_DECL void soci_use_uint64(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); - if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) || - name_unique_check_failed(*wrapper, statement_wrapper::bulk, name)) + if (cannot_add_elements(*wrapper, statement_wrapper::single, false) || + name_unique_check_failed(*wrapper, statement_wrapper::single, name)) { return; } wrapper->statement_state = statement_wrapper::defining; - wrapper->use_kind = statement_wrapper::bulk; + wrapper->use_kind = statement_wrapper::single; - wrapper->use_indicators_v[name]; // create new entry - wrapper->use_longlongs_v[name]; // create new entry + wrapper->use_indicators[name] = i_ok; // create new entry + wrapper->use_uint64[name]; // create new entry } -SOCI_DECL void soci_use_double_v(statement_handle st, char const * name) +SOCI_DECL void soci_use_double(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); - if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) || - name_unique_check_failed(*wrapper, statement_wrapper::bulk, name)) + if (cannot_add_elements(*wrapper, statement_wrapper::single, false) || + name_unique_check_failed(*wrapper, statement_wrapper::single, name)) { return; } wrapper->statement_state = statement_wrapper::defining; - wrapper->use_kind = statement_wrapper::bulk; + wrapper->use_kind = statement_wrapper::single; - wrapper->use_indicators_v[name]; // create new entry - wrapper->use_doubles_v[name]; // create new entry + wrapper->use_indicators[name] = i_ok; // create new entry + wrapper->use_doubles[name]; // create new entry } -SOCI_DECL void soci_use_date_v(statement_handle st, char const * name) +SOCI_DECL void soci_use_date(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); - if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) || - name_unique_check_failed(*wrapper, statement_wrapper::bulk, name)) + if (cannot_add_elements(*wrapper, statement_wrapper::single, false) || + name_unique_check_failed(*wrapper, statement_wrapper::single, name)) { return; } wrapper->statement_state = statement_wrapper::defining; - wrapper->use_kind = statement_wrapper::bulk; + wrapper->use_kind = statement_wrapper::single; - wrapper->use_indicators_v[name]; // create new entry - wrapper->use_dates_v[name]; // create new entry + wrapper->use_indicators[name] = i_ok; // create new entry + wrapper->use_dates[name]; // create new entry } -SOCI_DECL void soci_set_use_state(statement_handle st, char const * name, int state) +SOCI_DECL void soci_use_blob(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); - typedef std::map::const_iterator iterator; - iterator const it = wrapper->use_indicators.find(name); - if (it == wrapper->use_indicators.end()) + if (cannot_add_elements(*wrapper, statement_wrapper::single, false) || + name_unique_check_failed(*wrapper, statement_wrapper::single, name)) { - wrapper->is_ok = false; - wrapper->error_message = "Invalid name."; return; } - wrapper->is_ok = true; - wrapper->use_indicators[name] = (state != 0 ? i_ok : i_null); -} + wrapper->statement_state = statement_wrapper::defining; + wrapper->use_kind = statement_wrapper::single; -SOCI_DECL void soci_set_use_string(statement_handle st, char const * name, char const * val) + wrapper->use_indicators[name] = i_null; // create new entry + wrapper->use_blob[name] = soci_create_blob_session(wrapper->sql); // create new entry +} + +SOCI_DECL void soci_use_string_v(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) || + name_unique_check_failed(*wrapper, statement_wrapper::bulk, name)) + { + return; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->use_kind = statement_wrapper::bulk; + + wrapper->use_indicators_v[name]; // create new entry + wrapper->use_strings_v[name]; // create new entry +} + +SOCI_DECL void soci_use_int8_v(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) || + name_unique_check_failed(*wrapper, statement_wrapper::bulk, name)) + { + return; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->use_kind = statement_wrapper::bulk; + + wrapper->use_indicators_v[name]; // create new entry + wrapper->use_int8_v[name]; // create new entry +} + +SOCI_DECL void soci_use_uint8_v(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) || + name_unique_check_failed(*wrapper, statement_wrapper::bulk, name)) + { + return; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->use_kind = statement_wrapper::bulk; + + wrapper->use_indicators_v[name]; // create new entry + wrapper->use_uint8_v[name]; // create new entry +} + +SOCI_DECL void soci_use_int16_v(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) || + name_unique_check_failed(*wrapper, statement_wrapper::bulk, name)) + { + return; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->use_kind = statement_wrapper::bulk; + + wrapper->use_indicators_v[name]; // create new entry + wrapper->use_int16_v[name]; // create new entry +} + +SOCI_DECL void soci_use_uint16_v(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) || + name_unique_check_failed(*wrapper, statement_wrapper::bulk, name)) + { + return; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->use_kind = statement_wrapper::bulk; + + wrapper->use_indicators_v[name]; // create new entry + wrapper->use_uint16_v[name]; // create new entry +} + +SOCI_DECL void soci_use_int32_v(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) || + name_unique_check_failed(*wrapper, statement_wrapper::bulk, name)) + { + return; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->use_kind = statement_wrapper::bulk; + + wrapper->use_indicators_v[name]; // create new entry + wrapper->use_int32_v[name]; // create new entry +} + +SOCI_DECL void soci_use_uint32_v(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) || + name_unique_check_failed(*wrapper, statement_wrapper::bulk, name)) + { + return; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->use_kind = statement_wrapper::bulk; + + wrapper->use_indicators_v[name]; // create new entry + wrapper->use_uint32_v[name]; // create new entry +} + +SOCI_DECL void soci_use_int64_v(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) || + name_unique_check_failed(*wrapper, statement_wrapper::bulk, name)) + { + return; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->use_kind = statement_wrapper::bulk; + + wrapper->use_indicators_v[name]; // create new entry + wrapper->use_int64_v[name]; // create new entry +} + +SOCI_DECL void soci_use_uint64_v(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) || + name_unique_check_failed(*wrapper, statement_wrapper::bulk, name)) + { + return; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->use_kind = statement_wrapper::bulk; + + wrapper->use_indicators_v[name]; // create new entry + wrapper->use_uint64_v[name]; // create new entry +} + +SOCI_DECL void soci_use_double_v(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) || + name_unique_check_failed(*wrapper, statement_wrapper::bulk, name)) + { + return; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->use_kind = statement_wrapper::bulk; + + wrapper->use_indicators_v[name]; // create new entry + wrapper->use_doubles_v[name]; // create new entry +} + +SOCI_DECL void soci_use_date_v(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) || + name_unique_check_failed(*wrapper, statement_wrapper::bulk, name)) + { + return; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->use_kind = statement_wrapper::bulk; + + wrapper->use_indicators_v[name]; // create new entry + wrapper->use_dates_v[name]; // create new entry +} + +SOCI_DECL void soci_set_use_state(statement_handle st, char const * name, int state) +{ + statement_wrapper * wrapper = static_cast(st); + + typedef std::map::const_iterator iterator; + iterator const it = wrapper->use_indicators.find(name); + if (it == wrapper->use_indicators.end()) + { + wrapper->is_ok = false; + wrapper->error_message = "Invalid name."; + return; + } + + wrapper->is_ok = true; + wrapper->use_indicators[name] = (state != 0 ? i_ok : i_null); +} + +SOCI_DECL void soci_set_use_string(statement_handle st, char const * name, char const * val) { statement_wrapper * wrapper = static_cast(st); @@ -1494,32 +2266,116 @@ SOCI_DECL void soci_set_use_string(statement_handle st, char const * name, char wrapper->use_strings[name] = val; } -SOCI_DECL void soci_set_use_int(statement_handle st, char const * name, int val) +SOCI_DECL void soci_set_use_int8(statement_handle st, char const * name, int8_t val) { statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_integer, statement_wrapper::single, "int")) + name, dt_int8, statement_wrapper::single, "int8")) { return; } wrapper->use_indicators[name] = i_ok; - wrapper->use_ints[name] = val; + wrapper->use_int8[name] = val; } -SOCI_DECL void soci_set_use_long_long(statement_handle st, char const * name, long long val) +SOCI_DECL void soci_set_use_uint8(statement_handle st, char const * name, uint32_t val) { statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_long_long, statement_wrapper::single, "long long")) + name, dt_uint32, statement_wrapper::single, "uint32")) { return; } wrapper->use_indicators[name] = i_ok; - wrapper->use_longlongs[name] = val; + wrapper->use_uint32[name] = val; +} + +SOCI_DECL void soci_set_use_int16(statement_handle st, char const * name, int16_t val) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, dt_int16, statement_wrapper::single, "int16")) + { + return; + } + + wrapper->use_indicators[name] = i_ok; + wrapper->use_int16[name] = val; +} + +SOCI_DECL void soci_set_use_uint16(statement_handle st, char const * name, uint16_t val) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, dt_uint16, statement_wrapper::single, "uint16")) + { + return; + } + + wrapper->use_indicators[name] = i_ok; + wrapper->use_uint16[name] = val; +} + +SOCI_DECL void soci_set_use_int32(statement_handle st, char const * name, int32_t val) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, dt_int32, statement_wrapper::single, "int32")) + { + return; + } + + wrapper->use_indicators[name] = i_ok; + wrapper->use_int32[name] = val; +} + +SOCI_DECL void soci_set_use_uint32(statement_handle st, char const * name, uint32_t val) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, dt_uint32, statement_wrapper::single, "uint32")) + { + return; + } + + wrapper->use_indicators[name] = i_ok; + wrapper->use_uint32[name] = val; +} + +SOCI_DECL void soci_set_use_int64(statement_handle st, char const * name, int64_t val) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, dt_int64, statement_wrapper::single, "int64")) + { + return; + } + + wrapper->use_indicators[name] = i_ok; + wrapper->use_int64[name] = val; +} + +SOCI_DECL void soci_set_use_uint64(statement_handle st, char const * name, uint64_t val) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, dt_uint64, statement_wrapper::single, "uint64")) + { + return; + } + + wrapper->use_indicators[name] = i_ok; + wrapper->use_uint64[name] = val; } SOCI_DECL void soci_set_use_double(statement_handle st, char const * name, double val) @@ -1557,109 +2413,241 @@ SOCI_DECL void soci_set_use_date(statement_handle st, char const * name, char co wrapper->use_dates[name] = dt; } -SOCI_DECL void soci_set_use_blob(statement_handle st, char const * name, blob_handle b) +SOCI_DECL void soci_set_use_blob(statement_handle st, char const * name, blob_handle b) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, dt_blob, statement_wrapper::single, "blob")) + { + return; + } + + soci::indicator &ind = wrapper->use_indicators[name]; + blob_wrapper *&blob = wrapper->use_blob[name]; + if (ind == i_null && blob != NULL) + soci_destroy_blob(blob); + + ind = i_ok; + blob = static_cast(b); +} + +SOCI_DECL int soci_use_get_size_v(statement_handle st) +{ + statement_wrapper * wrapper = static_cast(st); + + if (wrapper->use_kind != statement_wrapper::bulk) + { + wrapper->is_ok = false; + wrapper->error_message = "No vector use elements."; + return -1; + } + + if (wrapper->use_indicators_v.empty()) + { + wrapper->is_ok = false; + wrapper->error_message = "Empty indicators vector."; + return -1; + } + + return static_cast(wrapper->use_indicators_v.begin()->second.size()); +} + +SOCI_DECL void soci_use_resize_v(statement_handle st, int new_size) +{ + statement_wrapper * wrapper = static_cast(st); + + if (new_size <= 0) + { + wrapper->is_ok = false; + wrapper->error_message = "Invalid size."; + return; + } + + if (wrapper->use_kind != statement_wrapper::bulk) + { + wrapper->is_ok = false; + wrapper->error_message = "No vector use elements."; + return; + } + + resize_in_map(wrapper->use_indicators_v, new_size); + resize_in_map(wrapper->use_strings_v, new_size); + resize_in_map(wrapper->use_int8_v, new_size); + resize_in_map(wrapper->use_uint8_v, new_size); + resize_in_map(wrapper->use_int16_v, new_size); + resize_in_map(wrapper->use_uint16_v, new_size); + resize_in_map(wrapper->use_int32_v, new_size); + resize_in_map(wrapper->use_uint32_v, new_size); + resize_in_map(wrapper->use_int64_v, new_size); + resize_in_map(wrapper->use_uint64_v, new_size); + resize_in_map(wrapper->use_doubles_v, new_size); + resize_in_map(wrapper->use_dates_v, new_size); + + wrapper->is_ok = true; +} + +SOCI_DECL void soci_set_use_state_v(statement_handle st, + char const * name, int index, int state) +{ + statement_wrapper * wrapper = static_cast(st); + + typedef std::map >::iterator iterator; + iterator const it = wrapper->use_indicators_v.find(name); + if (it == wrapper->use_indicators_v.end()) + { + wrapper->is_ok = false; + wrapper->error_message = "Invalid name."; + return; + } + + std::vector & v = it->second; + if (index_check_failed(v, *wrapper, index)) + { + return; + } + + v[index] = (state != 0 ? i_ok : i_null); +} + +SOCI_DECL void soci_set_use_string_v(statement_handle st, + char const * name, int index, char const * val) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, dt_string, statement_wrapper::bulk, "vector string")) + { + return; + } + + std::vector & v = wrapper->use_strings_v[name]; + if (index_check_failed(v, *wrapper, index)) + { + return; + } + + wrapper->use_indicators_v[name][index] = i_ok; + v[index] = val; +} + +SOCI_DECL void soci_set_use_int8_v(statement_handle st, + char const * name, int index, int8_t val) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, dt_int8, statement_wrapper::bulk, "vector int8")) + { + return; + } + + std::vector & v = wrapper->use_int8_v[name]; + if (index_check_failed(v, *wrapper, index)) + { + return; + } + + wrapper->use_indicators_v[name][index] = i_ok; + v[index] = val; +} + +SOCI_DECL void soci_set_use_uint8_v(statement_handle st, + char const * name, int index, uint8_t val) { statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_blob, statement_wrapper::single, "blob")) + name, dt_uint8, statement_wrapper::bulk, "vector uint8")) { return; } - soci::indicator &ind = wrapper->use_indicators[name]; - blob_wrapper *&blob = wrapper->use_blob[name]; - if (ind == i_null && blob != NULL) - soci_destroy_blob(blob); + std::vector & v = wrapper->use_uint8_v[name]; + if (index_check_failed(v, *wrapper, index)) + { + return; + } - ind = i_ok; - blob = static_cast(b); + wrapper->use_indicators_v[name][index] = i_ok; + v[index] = val; } -SOCI_DECL int soci_use_get_size_v(statement_handle st) +SOCI_DECL void soci_set_use_int16_v(statement_handle st, + char const * name, int index, int16_t val) { statement_wrapper * wrapper = static_cast(st); - if (wrapper->use_kind != statement_wrapper::bulk) + if (name_exists_check_failed(*wrapper, + name, dt_int16, statement_wrapper::bulk, "vector int16")) { - wrapper->is_ok = false; - wrapper->error_message = "No vector use elements."; - return -1; + return; } - if (wrapper->use_indicators_v.empty()) + std::vector & v = wrapper->use_int16_v[name]; + if (index_check_failed(v, *wrapper, index)) { - wrapper->is_ok = false; - wrapper->error_message = "Empty indicators vector."; - return -1; + return; } - return static_cast(wrapper->use_indicators_v.begin()->second.size()); + wrapper->use_indicators_v[name][index] = i_ok; + v[index] = val; } -SOCI_DECL void soci_use_resize_v(statement_handle st, int new_size) +SOCI_DECL void soci_set_use_uint16_v(statement_handle st, + char const * name, int index, uint16_t val) { statement_wrapper * wrapper = static_cast(st); - if (new_size <= 0) + if (name_exists_check_failed(*wrapper, + name, dt_uint16, statement_wrapper::bulk, "vector uint16")) { - wrapper->is_ok = false; - wrapper->error_message = "Invalid size."; return; } - if (wrapper->use_kind != statement_wrapper::bulk) + std::vector & v = wrapper->use_uint16_v[name]; + if (index_check_failed(v, *wrapper, index)) { - wrapper->is_ok = false; - wrapper->error_message = "No vector use elements."; return; } - resize_in_map(wrapper->use_indicators_v, new_size); - resize_in_map(wrapper->use_strings_v, new_size); - resize_in_map(wrapper->use_ints_v, new_size); - resize_in_map(wrapper->use_longlongs_v, new_size); - resize_in_map(wrapper->use_doubles_v, new_size); - resize_in_map(wrapper->use_dates_v, new_size); - - wrapper->is_ok = true; + wrapper->use_indicators_v[name][index] = i_ok; + v[index] = val; } -SOCI_DECL void soci_set_use_state_v(statement_handle st, - char const * name, int index, int state) +SOCI_DECL void soci_set_use_int32_v(statement_handle st, + char const * name, int index, int32_t val) { statement_wrapper * wrapper = static_cast(st); - typedef std::map >::iterator iterator; - iterator const it = wrapper->use_indicators_v.find(name); - if (it == wrapper->use_indicators_v.end()) + if (name_exists_check_failed(*wrapper, + name, dt_int32, statement_wrapper::bulk, "vector int32")) { - wrapper->is_ok = false; - wrapper->error_message = "Invalid name."; return; } - std::vector & v = it->second; + std::vector & v = wrapper->use_int32_v[name]; if (index_check_failed(v, *wrapper, index)) { return; } - v[index] = (state != 0 ? i_ok : i_null); + wrapper->use_indicators_v[name][index] = i_ok; + v[index] = val; } -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_uint32_v(statement_handle st, + char const * name, int index, uint32_t val) { statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_string, statement_wrapper::bulk, "vector string")) + name, dt_uint32, statement_wrapper::bulk, "vector uint32")) { return; } - std::vector & v = wrapper->use_strings_v[name]; + std::vector & v = wrapper->use_uint32_v[name]; if (index_check_failed(v, *wrapper, index)) { return; @@ -1669,18 +2657,18 @@ SOCI_DECL void soci_set_use_string_v(statement_handle st, v[index] = 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_int64_v(statement_handle st, + char const * name, int index, int64_t val) { statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_integer, statement_wrapper::bulk, "vector int")) + name, dt_int64, statement_wrapper::bulk, "vector int64")) { return; } - std::vector & v = wrapper->use_ints_v[name]; + std::vector & v = wrapper->use_int64_v[name]; if (index_check_failed(v, *wrapper, index)) { return; @@ -1690,18 +2678,18 @@ SOCI_DECL void soci_set_use_int_v(statement_handle st, v[index] = 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_uint64_v(statement_handle st, + char const * name, int index, uint64_t val) { statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_long_long, statement_wrapper::bulk, "vector long long")) + name, dt_uint64, statement_wrapper::bulk, "vector uint64")) { return; } - std::vector & v = wrapper->use_longlongs_v[name]; + std::vector & v = wrapper->use_uint64_v[name]; if (index_check_failed(v, *wrapper, index)) { return; @@ -1790,30 +2778,108 @@ SOCI_DECL char const * soci_get_use_string(statement_handle st, char const * nam return wrapper->use_strings[name].c_str(); } -SOCI_DECL int soci_get_use_int(statement_handle st, char const * name) +SOCI_DECL int8_t soci_get_use_int8(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_integer, statement_wrapper::bulk, "int")) + name, dt_int8, statement_wrapper::bulk, "int8")) { return 0; } - return wrapper->use_ints[name]; + return wrapper->use_int8[name]; } -SOCI_DECL long long soci_get_use_long_long(statement_handle st, char const * name) +SOCI_DECL uint8_t soci_get_use_uint8(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_long_long, statement_wrapper::bulk, "long long")) + name, dt_uint8, statement_wrapper::bulk, "uint8")) + { + return 0; + } + + return wrapper->use_uint8[name]; +} + +SOCI_DECL int16_t soci_get_use_int16(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, dt_int16, statement_wrapper::bulk, "int16")) + { + return 0; + } + + return wrapper->use_int16[name]; +} + +SOCI_DECL uint16_t soci_get_use_uint16(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, dt_uint16, statement_wrapper::bulk, "uint16")) + { + return 0; + } + + return wrapper->use_uint16[name]; +} + +SOCI_DECL int32_t soci_get_use_int32(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, dt_int32, statement_wrapper::bulk, "int32")) + { + return 0; + } + + return wrapper->use_int32[name]; +} + +SOCI_DECL uint32_t soci_get_use_uint32(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, dt_uint32, statement_wrapper::bulk, "uint32")) + { + return 0; + } + + return wrapper->use_uint32[name]; +} + +SOCI_DECL int64_t soci_get_use_int64(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, dt_int64, statement_wrapper::bulk, "int64")) + { + return 0LL; + } + + return wrapper->use_int64[name]; +} + +SOCI_DECL uint64_t soci_get_use_uint64(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, dt_uint64, statement_wrapper::bulk, "uint64")) { return 0LL; } - return wrapper->use_longlongs[name]; + return wrapper->use_uint64[name]; } SOCI_DECL double soci_get_use_double(statement_handle st, char const * name) @@ -1882,14 +2948,37 @@ SOCI_DECL void soci_prepare(statement_handle st, char const * query) wrapper->st.exchange( into(wrapper->into_strings[i], wrapper->into_indicators[i])); break; - case dt_integer: + case dt_int8: + wrapper->st.exchange( + into(wrapper->into_int8[i], wrapper->into_indicators[i])); + break; + case dt_uint8: + wrapper->st.exchange( + into(wrapper->into_uint8[i], wrapper->into_indicators[i])); + break; + case dt_int16: wrapper->st.exchange( - into(wrapper->into_ints[i], wrapper->into_indicators[i])); + into(wrapper->into_int16[i], wrapper->into_indicators[i])); break; - case dt_long_long: - case dt_unsigned_long_long: + case dt_uint16: wrapper->st.exchange( - into(wrapper->into_longlongs[i], wrapper->into_indicators[i])); + into(wrapper->into_uint16[i], wrapper->into_indicators[i])); + break; + case dt_int32: + wrapper->st.exchange( + into(wrapper->into_int32[i], wrapper->into_indicators[i])); + break; + case dt_uint32: + wrapper->st.exchange( + into(wrapper->into_uint32[i], wrapper->into_indicators[i])); + break; + case dt_int64: + wrapper->st.exchange( + into(wrapper->into_int64[i], wrapper->into_indicators[i])); + break; + case dt_uint64: + wrapper->st.exchange( + into(wrapper->into_uint64[i], wrapper->into_indicators[i])); break; case dt_double: wrapper->st.exchange( @@ -1920,14 +3009,37 @@ SOCI_DECL void soci_prepare(statement_handle st, char const * query) wrapper->st.exchange( into(wrapper->into_strings_v[i], wrapper->into_indicators_v[i])); break; - case dt_integer: + case dt_int8: + wrapper->st.exchange( + into(wrapper->into_int8_v[i], wrapper->into_indicators_v[i])); + break; + case dt_uint8: + wrapper->st.exchange( + into(wrapper->into_uint8_v[i], wrapper->into_indicators_v[i])); + break; + case dt_int16: + wrapper->st.exchange( + into(wrapper->into_int16_v[i], wrapper->into_indicators_v[i])); + break; + case dt_uint16: + wrapper->st.exchange( + into(wrapper->into_uint16_v[i], wrapper->into_indicators_v[i])); + break; + case dt_int32: wrapper->st.exchange( - into(wrapper->into_ints_v[i], wrapper->into_indicators_v[i])); + into(wrapper->into_int32_v[i], wrapper->into_indicators_v[i])); break; - case dt_long_long: - case dt_unsigned_long_long: + case dt_uint32: wrapper->st.exchange( - into(wrapper->into_longlongs_v[i], wrapper->into_indicators_v[i])); + into(wrapper->into_uint32_v[i], wrapper->into_indicators_v[i])); + break; + case dt_int64: + wrapper->st.exchange( + into(wrapper->into_int64_v[i], wrapper->into_indicators_v[i])); + break; + case dt_uint64: + wrapper->st.exchange( + into(wrapper->into_uint64_v[i], wrapper->into_indicators_v[i])); break; case dt_double: wrapper->st.exchange( @@ -1960,27 +3072,105 @@ SOCI_DECL void soci_prepare(statement_handle st, char const * query) } } { - // ints - typedef std::map::iterator iterator; - iterator uit = wrapper->use_ints.begin(); - iterator const uend = wrapper->use_ints.end(); + // int8 + typedef std::map::iterator iterator; + iterator uit = wrapper->use_int8.begin(); + iterator const uend = wrapper->use_int8.end(); + for ( ; uit != uend; ++uit) + { + std::string const & use_name = uit->first; + int8_t & use_int = uit->second; + indicator & use_ind = wrapper->use_indicators[use_name]; + wrapper->st.exchange(use(use_int, use_ind, use_name)); + } + } + { + // uint8 + typedef std::map::iterator iterator; + iterator uit = wrapper->use_uint8.begin(); + iterator const uend = wrapper->use_uint8.end(); + for ( ; uit != uend; ++uit) + { + std::string const & use_name = uit->first; + uint8_t & use_int = uit->second; + indicator & use_ind = wrapper->use_indicators[use_name]; + wrapper->st.exchange(use(use_int, use_ind, use_name)); + } + } + { + // int16 + typedef std::map::iterator iterator; + iterator uit = wrapper->use_int16.begin(); + iterator const uend = wrapper->use_int16.end(); + for ( ; uit != uend; ++uit) + { + std::string const & use_name = uit->first; + int16_t & use_int = uit->second; + indicator & use_ind = wrapper->use_indicators[use_name]; + wrapper->st.exchange(use(use_int, use_ind, use_name)); + } + } + { + // uint16 + typedef std::map::iterator iterator; + iterator uit = wrapper->use_uint16.begin(); + iterator const uend = wrapper->use_uint16.end(); + for ( ; uit != uend; ++uit) + { + std::string const & use_name = uit->first; + uint16_t & use_int = uit->second; + indicator & use_ind = wrapper->use_indicators[use_name]; + wrapper->st.exchange(use(use_int, use_ind, use_name)); + } + } + { + // int32 + typedef std::map::iterator iterator; + iterator uit = wrapper->use_int32.begin(); + iterator const uend = wrapper->use_int32.end(); + for ( ; uit != uend; ++uit) + { + std::string const & use_name = uit->first; + int32_t & use_int = uit->second; + indicator & use_ind = wrapper->use_indicators[use_name]; + wrapper->st.exchange(use(use_int, use_ind, use_name)); + } + } + { + // uint32 + typedef std::map::iterator iterator; + iterator uit = wrapper->use_uint32.begin(); + iterator const uend = wrapper->use_uint32.end(); for ( ; uit != uend; ++uit) { std::string const & use_name = uit->first; - int & use_int = uit->second; + uint32_t & use_int = uit->second; indicator & use_ind = wrapper->use_indicators[use_name]; wrapper->st.exchange(use(use_int, use_ind, use_name)); } } { - // longlongs - typedef std::map::iterator iterator; - iterator uit = wrapper->use_longlongs.begin(); - iterator const uend = wrapper->use_longlongs.end(); + // int64 + typedef std::map::iterator iterator; + iterator uit = wrapper->use_int64.begin(); + iterator const uend = wrapper->use_int64.end(); + for ( ; uit != uend; ++uit) + { + std::string const & use_name = uit->first; + int64_t & use_longlong = uit->second; + indicator & use_ind = wrapper->use_indicators[use_name]; + wrapper->st.exchange(use(use_longlong, use_ind, use_name)); + } + } + { + // uint64 + typedef std::map::iterator iterator; + iterator uit = wrapper->use_uint64.begin(); + iterator const uend = wrapper->use_uint64.end(); for ( ; uit != uend; ++uit) { std::string const & use_name = uit->first; - long long & use_longlong = uit->second; + uint64_t & use_longlong = uit->second; indicator & use_ind = wrapper->use_indicators[use_name]; wrapper->st.exchange(use(use_longlong, use_ind, use_name)); } @@ -2042,30 +3232,120 @@ SOCI_DECL void soci_prepare(statement_handle st, char const * query) } } { - // ints + // int8 + typedef std::map >::iterator iterator; + iterator uit = wrapper->use_int8_v.begin(); + iterator const uend = wrapper->use_int8_v.end(); + for ( ; uit != uend; ++uit) + { + std::string const & use_name = uit->first; + std::vector & use_int = uit->second; + std::vector & use_ind = + wrapper->use_indicators_v[use_name]; + wrapper->st.exchange(use(use_int, use_ind, use_name)); + } + } + { + // uint8 + typedef std::map >::iterator iterator; + iterator uit = wrapper->use_uint8_v.begin(); + iterator const uend = wrapper->use_uint8_v.end(); + for ( ; uit != uend; ++uit) + { + std::string const & use_name = uit->first; + std::vector & use_int = uit->second; + std::vector & use_ind = + wrapper->use_indicators_v[use_name]; + wrapper->st.exchange(use(use_int, use_ind, use_name)); + } + } + { + // int16 + typedef std::map >::iterator iterator; + iterator uit = wrapper->use_int16_v.begin(); + iterator const uend = wrapper->use_int16_v.end(); + for ( ; uit != uend; ++uit) + { + std::string const & use_name = uit->first; + std::vector & use_int = uit->second; + std::vector & use_ind = + wrapper->use_indicators_v[use_name]; + wrapper->st.exchange(use(use_int, use_ind, use_name)); + } + } + { + // uint16 + typedef std::map >::iterator iterator; + iterator uit = wrapper->use_uint16_v.begin(); + iterator const uend = wrapper->use_uint16_v.end(); + for ( ; uit != uend; ++uit) + { + std::string const & use_name = uit->first; + std::vector & use_int = uit->second; + std::vector & use_ind = + wrapper->use_indicators_v[use_name]; + wrapper->st.exchange(use(use_int, use_ind, use_name)); + } + } + { + // int32 + typedef std::map >::iterator iterator; + iterator uit = wrapper->use_int32_v.begin(); + iterator const uend = wrapper->use_int32_v.end(); + for ( ; uit != uend; ++uit) + { + std::string const & use_name = uit->first; + std::vector & use_int = uit->second; + std::vector & use_ind = + wrapper->use_indicators_v[use_name]; + wrapper->st.exchange(use(use_int, use_ind, use_name)); + } + } + { + // uint32 typedef std::map >::iterator iterator; - iterator uit = wrapper->use_ints_v.begin(); - iterator const uend = wrapper->use_ints_v.end(); + std::vector >::iterator iterator; + iterator uit = wrapper->use_uint32_v.begin(); + iterator const uend = wrapper->use_uint32_v.end(); for ( ; uit != uend; ++uit) { std::string const & use_name = uit->first; - std::vector & use_int = uit->second; + std::vector & use_int = uit->second; std::vector & use_ind = wrapper->use_indicators_v[use_name]; wrapper->st.exchange(use(use_int, use_ind, use_name)); } } { - // longlongs + // int64 + typedef std::map >::iterator iterator; + iterator uit = wrapper->use_int64_v.begin(); + iterator const uend = wrapper->use_int64_v.end(); + for ( ; uit != uend; ++uit) + { + std::string const & use_name = uit->first; + std::vector & use_longlong = uit->second; + std::vector & use_ind = + wrapper->use_indicators_v[use_name]; + wrapper->st.exchange(use(use_longlong, use_ind, use_name)); + } + } + { + // uint64 typedef std::map >::iterator iterator; - iterator uit = wrapper->use_longlongs_v.begin(); - iterator const uend = wrapper->use_longlongs_v.end(); + std::vector >::iterator iterator; + iterator uit = wrapper->use_uint64_v.begin(); + iterator const uend = wrapper->use_uint64_v.end(); for ( ; uit != uend; ++uit) { std::string const & use_name = uit->first; - std::vector & use_longlong = uit->second; + std::vector & use_longlong = uit->second; std::vector & use_ind = wrapper->use_indicators_v[use_name]; wrapper->st.exchange(use(use_longlong, use_ind, use_name)); From 9e39f9793cae7828567b41533b3d220fb114e98f Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Tue, 5 Apr 2022 23:11:55 +0200 Subject: [PATCH 10/46] Update shared unit tests for complete integer type support --- tests/common-tests.h | 661 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 643 insertions(+), 18 deletions(-) diff --git a/tests/common-tests.h b/tests/common-tests.h index ee791d591..1e861ef58 100644 --- a/tests/common-tests.h +++ b/tests/common-tests.h @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -461,6 +462,15 @@ class test_context_base // to fit by default. virtual bool has_silent_truncate_bug(session&) const { return false; } + // Override this if the backend doesn't fully support signed 8-bit integers. + virtual bool has_full_int8_support() const { return true; } + + // Override this if the backend doesn't support unsigned types. + virtual bool has_full_unsigned_type_support() const { return true; } + + // Override this if the backend doesn't fully support unsigned 64-bit integers. + virtual bool has_full_uint64_support() const { return true; } + // Override this if the backend doesn't distinguish between empty and null // strings (Oracle does this). virtual bool treats_empty_strings_as_null() const { return false; } @@ -1512,6 +1522,78 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") CHECK(str == "Hello SOCI!"); } + SECTION("int8_t") + { + int8_t s = 123; + sql << "insert into soci_test(id) values(:id)", use(s); + + int8_t s2 = 0; + sql << "select id from soci_test", into(s2); + + CHECK(s2 == 123); + } + + SECTION("int8_t min") + { + if (!tc_.has_full_int8_support()) + { + WARN("int8 not fully supported by the database, skipping the test."); + return; + } + + int8_t s = (std::numeric_limits::min)(); + sql << "insert into soci_test(id) values(:id)", use(s); + + int8_t s2 = 0; + sql << "select id from soci_test", into(s2); + + CHECK(s2 == (std::numeric_limits::min)()); + } + + SECTION("int8_t max") + { + int8_t s = (std::numeric_limits::max)(); + sql << "insert into soci_test(id) values(:id)", use(s); + + int8_t s2 = 0; + sql << "select id from soci_test", into(s2); + + CHECK(s2 == (std::numeric_limits::max)()); + } + + SECTION("uint8_t") + { + uint8_t s = 123; + sql << "insert into soci_test(id) values(:id)", use(s); + + uint8_t s2 = 0; + sql << "select id from soci_test", into(s2); + + CHECK(s2 == 123); + } + + SECTION("uint8_t min") + { + uint8_t s = (std::numeric_limits::min)(); + sql << "insert into soci_test(id) values(:id)", use(s); + + uint8_t s2 = 0; + sql << "select id from soci_test", into(s2); + + CHECK(s2 == (std::numeric_limits::min)()); + } + + SECTION("uint8_t max") + { + uint8_t s = (std::numeric_limits::max)(); + sql << "insert into soci_test(id) values(:id)", use(s); + + uint8_t s2 = 0; + sql << "select id from soci_test", into(s2); + + CHECK(s2 == (std::numeric_limits::max)()); + } + SECTION("short") { short s = 123; @@ -1523,6 +1605,78 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") CHECK(s2 == 123); } + SECTION("int16_t") + { + int16_t s = 123; + sql << "insert into soci_test(id) values(:id)", use(s); + + int16_t s2 = 0; + sql << "select id from soci_test", into(s2); + + CHECK(s2 == 123); + } + + SECTION("int16_t min") + { + int16_t s = (std::numeric_limits::min)(); + sql << "insert into soci_test(id) values(:id)", use(s); + + int16_t s2 = 0; + sql << "select id from soci_test", into(s2); + + CHECK(s2 == (std::numeric_limits::min)()); + } + + SECTION("int16_t max") + { + int16_t s = (std::numeric_limits::max)(); + sql << "insert into soci_test(id) values(:id)", use(s); + + int16_t s2 = 0; + sql << "select id from soci_test", into(s2); + + CHECK(s2 == (std::numeric_limits::max)()); + } + + SECTION("uint16_t") + { + uint16_t s = 123; + sql << "insert into soci_test(id) values(:id)", use(s); + + uint16_t s2 = 0; + sql << "select id from soci_test", into(s2); + + CHECK(s2 == 123); + } + + SECTION("uint16_t min") + { + uint16_t s = (std::numeric_limits::min)(); + sql << "insert into soci_test(id) values(:id)", use(s); + + uint16_t s2 = 0; + sql << "select id from soci_test", into(s2); + + CHECK(s2 == (std::numeric_limits::min)()); + } + + SECTION("uint16_t max") + { + if (!tc_.has_full_unsigned_type_support()) + { + WARN("uint16 not fully supported by the database, skipping the test."); + return; + } + + uint16_t s = (std::numeric_limits::max)(); + sql << "insert into soci_test(id) values(:id)", use(s); + + uint16_t s2 = 0; + sql << "select id from soci_test", into(s2); + + CHECK(s2 == (std::numeric_limits::max)()); + } + SECTION("int") { int i = -12345678; @@ -1534,8 +1688,86 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") CHECK(i2 == -12345678); } + SECTION("int32_t") + { + int32_t i = -12345678; + sql << "insert into soci_test(id) values(:i)", use(i); + + int32_t i2 = 0; + sql << "select id from soci_test", into(i2); + + CHECK(i2 == -12345678); + } + + SECTION("int32_t min") + { + int32_t i = (std::numeric_limits::min)(); + sql << "insert into soci_test(id) values(:i)", use(i); + + int32_t i2 = 0; + sql << "select id from soci_test", into(i2); + + CHECK(i2 == (std::numeric_limits::min)()); + } + + SECTION("int32_t max") + { + int32_t i = (std::numeric_limits::max)(); + sql << "insert into soci_test(id) values(:i)", use(i); + + int32_t i2 = 0; + sql << "select id from soci_test", into(i2); + + CHECK(i2 == (std::numeric_limits::max)()); + } + + SECTION("uint32_t") + { + uint32_t i = 12345678; + sql << "insert into soci_test(id) values(:i)", use(i); + + uint32_t i2 = 0; + sql << "select id from soci_test", into(i2); + + CHECK(i2 == 12345678); + } + + SECTION("uint32_t min") + { + uint32_t i = (std::numeric_limits::min)(); + sql << "insert into soci_test(id) values(:i)", use(i); + + uint32_t i2 = 0; + sql << "select id from soci_test", into(i2); + + CHECK(i2 == (std::numeric_limits::min)()); + } + + SECTION("uint32_t max") + { + if (!tc_.has_full_unsigned_type_support()) + { + WARN("uint32 not fully supported by the database, skipping the test."); + return; + } + + uint32_t i = (std::numeric_limits::max)(); + sql << "insert into soci_test(ul) values(:i)", use(i); + + uint32_t i2 = 0; + sql << "select ul from soci_test", into(i2); + + CHECK(i2 == (std::numeric_limits::max)()); + } + SECTION("unsigned long") { + if (!tc_.has_full_unsigned_type_support()) + { + WARN("unsigned long not fully supported by the database, skipping the test."); + return; + } + unsigned long ul = 4000000000ul; sql << "insert into soci_test(ul) values(:num)", use(ul); @@ -1545,6 +1777,78 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") CHECK(ul2 == 4000000000ul); } + SECTION("int64_t") + { + int64_t ll = 4000000000ll; + sql << "insert into soci_test(ll) values(:num)", use(ll); + + int64_t ll2 = 0; + sql << "select ll from soci_test", into(ll2); + + CHECK(ll2 == 4000000000ll); + } + + SECTION("int64_t min") + { + int64_t ll = (std::numeric_limits::min)(); + sql << "insert into soci_test(ll) values(:num)", use(ll); + + int64_t ll2 = 0; + sql << "select ll from soci_test", into(ll2); + + CHECK(ll2 == (std::numeric_limits::min)()); + } + + SECTION("int64_t max") + { + int64_t ll = (std::numeric_limits::max)(); + sql << "insert into soci_test(ll) values(:num)", use(ll); + + int64_t ll2 = 0; + sql << "select ll from soci_test", into(ll2); + + CHECK(ll2 == (std::numeric_limits::max)()); + } + + SECTION("uint64_t") + { + uint64_t ul = 4000000000ull; + sql << "insert into soci_test(ul) values(:num)", use(ul); + + uint64_t ul2 = 0; + sql << "select ul from soci_test", into(ul2); + + CHECK(ul2 == 4000000000ull); + } + + SECTION("uint64_t min") + { + uint64_t ul = (std::numeric_limits::min)(); + sql << "insert into soci_test(ul) values(:num)", use(ul); + + uint64_t ul2 = 0; + sql << "select ul from soci_test", into(ul2); + + CHECK(ul2 == (std::numeric_limits::min)()); + } + + SECTION("uint64_t max") + { + if (!tc_.has_full_unsigned_type_support() || !tc_.has_full_uint64_support()) + { + WARN("uint64 not fully supported by the database, skipping the test."); + return; + } + + uint64_t ul = (std::numeric_limits::max)(); + sql << "insert into soci_test(ul) values(:num)", use(ul); + + uint64_t ul2 = 0; + sql << "select ul from soci_test", into(ul2); + + CHECK(ul2 == (std::numeric_limits::max)()); + } + SECTION("double") { double d = 3.14159265; @@ -1631,6 +1935,28 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") CHECK(str == "Hello const SOCI!"); } + SECTION("const int8_t") + { + int8_t const s = 123; + sql << "insert into soci_test(id) values(:id)", use(s); + + int8_t s2 = 0; + sql << "select id from soci_test", into(s2); + + CHECK(s2 == 123); + } + + SECTION("const uint8_t") + { + uint8_t const s = 123; + sql << "insert into soci_test(id) values(:id)", use(s); + + uint8_t s2 = 0; + sql << "select id from soci_test", into(s2); + + CHECK(s2 == 123); + } + SECTION("const short") { short const s = 123; @@ -1642,6 +1968,28 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") CHECK(s2 == 123); } + SECTION("const int16_t") + { + int16_t const s = 123; + sql << "insert into soci_test(id) values(:id)", use(s); + + int16_t s2 = 0; + sql << "select id from soci_test", into(s2); + + CHECK(s2 == 123); + } + + SECTION("const uint16_t") + { + uint16_t const s = 123; + sql << "insert into soci_test(id) values(:id)", use(s); + + uint16_t s2 = 0; + sql << "select id from soci_test", into(s2); + + CHECK(s2 == 123); + } + SECTION("const int") { int const i = -12345678; @@ -1653,8 +2001,36 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") CHECK(i2 == -12345678); } + SECTION("const int32_t") + { + int32_t const i = -12345678; + sql << "insert into soci_test(id) values(:i)", use(i); + + int32_t i2 = 0; + sql << "select id from soci_test", into(i2); + + CHECK(i2 == -12345678); + } + + SECTION("const uint32_t") + { + uint32_t const i = 12345678; + sql << "insert into soci_test(id) values(:i)", use(i); + + uint32_t i2 = 0; + sql << "select id from soci_test", into(i2); + + CHECK(i2 == 12345678); + } + SECTION("const unsigned long") { + if (!tc_.has_full_unsigned_type_support()) + { + WARN("unsigned long not fully supported by the database, skipping the test."); + return; + } + unsigned long const ul = 4000000000ul; sql << "insert into soci_test(ul) values(:num)", use(ul); @@ -1664,6 +2040,28 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") CHECK(ul2 == 4000000000ul); } + SECTION("const int64_t") + { + int64_t const ul = 4000000000ll; + sql << "insert into soci_test(ul) values(:num)", use(ul); + + int64_t ul2 = 0; + sql << "select ul from soci_test", into(ul2); + + CHECK(ul2 == 4000000000ll); + } + + SECTION("const uint64_t") + { + uint64_t const ul = 4000000000ull; + sql << "insert into soci_test(ul) values(:num)", use(ul); + + uint64_t ul2 = 0; + sql << "select ul from soci_test", into(ul2); + + CHECK(ul2 == 4000000000ull); + } + SECTION("const double") { double const d = 3.14159265; @@ -1821,6 +2219,58 @@ TEST_CASE_METHOD(common_tests, "Use vector", "[core][use][vector]") CHECK(v2[2] == "ma"); } + SECTION("int8_t") + { + std::vector v; + if (tc_.has_full_int8_support()) + { + v.push_back((std::numeric_limits::min)()); + v.push_back(-5); + } + v.push_back(123); + v.push_back((std::numeric_limits::max)()); + + sql << "insert into soci_test(sh) values(:sh)", use(v); + + std::vector v2(4); + + sql << "select sh from soci_test order by sh", into(v2); + if (tc_.has_full_int8_support()) + { + CHECK(v2.size() == 4); + CHECK(v2[0] == (std::numeric_limits::min)()); + CHECK(v2[1] == -5); + CHECK(v2[2] == 123); + CHECK(v2[3] == (std::numeric_limits::max)()); + } + else + { + CHECK(v2.size() == 2); + CHECK(v2[0] == 123); + CHECK(v2[1] == (std::numeric_limits::max)()); + } + } + + SECTION("uint8_t") + { + std::vector v; + v.push_back((std::numeric_limits::min)()); + v.push_back(6); + v.push_back(123); + v.push_back((std::numeric_limits::max)()); + + sql << "insert into soci_test(sh) values(:sh)", use(v); + + std::vector v2(4); + + sql << "select sh from soci_test order by sh", into(v2); + CHECK(v2.size() == 4); + CHECK(v2[0] == (std::numeric_limits::min)()); + CHECK(v2[1] == 6); + CHECK(v2[2] == 123); + CHECK(v2[3] == (std::numeric_limits::max)()); + } + SECTION("short") { std::vector v; @@ -1841,6 +2291,59 @@ TEST_CASE_METHOD(common_tests, "Use vector", "[core][use][vector]") CHECK(v2[3] == 123); } + SECTION("int16_t") + { + std::vector v; + v.push_back((std::numeric_limits::min)()); + v.push_back(-5); + v.push_back(123); + v.push_back((std::numeric_limits::max)()); + + sql << "insert into soci_test(sh) values(:sh)", use(v); + + std::vector v2(4); + + sql << "select sh from soci_test order by sh", into(v2); + CHECK(v2.size() == 4); + CHECK(v2[0] == (std::numeric_limits::min)()); + CHECK(v2[1] == -5); + CHECK(v2[2] == 123); + CHECK(v2[3] == (std::numeric_limits::max)()); + } + + SECTION("uint16_t") + { + std::vector v; + v.push_back((std::numeric_limits::min)()); + v.push_back(6); + v.push_back(123); + if (tc_.has_full_unsigned_type_support()) + { + v.push_back((std::numeric_limits::max)()); + } + + sql << "insert into soci_test(val) values(:val)", use(v); + + std::vector v2(4); + + sql << "select val from soci_test order by val", into(v2); + if (tc_.has_full_unsigned_type_support()) + { + CHECK(v2.size() == 4); + } + else + { + CHECK(v2.size() == 3); + } + CHECK(v2[0] == (std::numeric_limits::min)()); + CHECK(v2[1] == 6); + CHECK(v2[2] == 123); + if (tc_.has_full_unsigned_type_support()) + { + CHECK(v2[3] == (std::numeric_limits::max)()); + } + } + SECTION("int") { std::vector v; @@ -1861,6 +2364,30 @@ TEST_CASE_METHOD(common_tests, "Use vector", "[core][use][vector]") CHECK(v2[3] == 2000000000); } + SECTION("int32_t") + { + std::vector v; + v.push_back((std::numeric_limits::min)()); + v.push_back(-2000000000); + v.push_back(0); + v.push_back(1); + v.push_back(2000000000); + v.push_back((std::numeric_limits::max)()); + + sql << "insert into soci_test(id) values(:i)", use(v); + + std::vector v2(6); + + sql << "select id from soci_test order by id", into(v2); + CHECK(v2.size() == 6); + CHECK(v2[0] == (std::numeric_limits::min)()); + CHECK(v2[1] == -2000000000); + CHECK(v2[2] == 0); + CHECK(v2[3] == 1); + CHECK(v2[4] == 2000000000); + CHECK(v2[5] == (std::numeric_limits::max)()); + } + SECTION("unsigned int") { std::vector v; @@ -1881,6 +2408,43 @@ TEST_CASE_METHOD(common_tests, "Use vector", "[core][use][vector]") CHECK(v2[3] == 1000); } + SECTION("uint32_t") + { + std::vector v; + v.push_back((std::numeric_limits::min)()); + v.push_back(0); + v.push_back(1); + v.push_back(123); + v.push_back(1000); + if (tc_.has_full_unsigned_type_support()) + { + v.push_back((std::numeric_limits::max)()); + } + + sql << "insert into soci_test(ul) values(:ul)", use(v); + + std::vector v2(6); + + sql << "select ul from soci_test order by ul", into(v2); + if (tc_.has_full_unsigned_type_support()) + { + CHECK(v2.size() == 6); + } + else + { + CHECK(v2.size() == 5); + } + CHECK(v2[0] == (std::numeric_limits::min)()); + CHECK(v2[1] == 0); + CHECK(v2[2] == 1); + CHECK(v2[3] == 123); + CHECK(v2[4] == 1000); + if (tc_.has_full_unsigned_type_support()) + { + CHECK(v2[5] == (std::numeric_limits::max)()); + } + } + SECTION("unsigned long long") { std::vector v; @@ -1901,6 +2465,67 @@ TEST_CASE_METHOD(common_tests, "Use vector", "[core][use][vector]") CHECK(v2[3] == 1000); } + SECTION("int64_t") + { + std::vector v; + v.push_back((std::numeric_limits::min)()); + v.push_back(0); + v.push_back(1); + v.push_back(123); + v.push_back(1000); + v.push_back((std::numeric_limits::max)()); + + sql << "insert into soci_test(ll) values(:ll)", use(v); + + std::vector v2(6); + + sql << "select ll from soci_test order by ll", into(v2); + CHECK(v2.size() == 6); + CHECK(v2[0] == (std::numeric_limits::min)()); + CHECK(v2[1] == 0); + CHECK(v2[2] == 1); + CHECK(v2[3] == 123); + CHECK(v2[4] == 1000); + CHECK(v2[5] == (std::numeric_limits::max)()); + } + + SECTION("uint64_t") + { + std::vector v; + v.push_back((std::numeric_limits::min)()); + v.push_back(0); + v.push_back(1); + v.push_back(123); + v.push_back(1000); + if (tc_.has_full_unsigned_type_support() && tc_.has_full_uint64_support()) + { + v.push_back((std::numeric_limits::max)()); + } + + sql << "insert into soci_test(ul) values(:ul)", use(v); + + std::vector v2(6); + + sql << "select ul from soci_test order by ul", into(v2); + if (tc_.has_full_unsigned_type_support() && tc_.has_full_uint64_support()) + { + CHECK(v2.size() == 6); + } + else + { + CHECK(v2.size() == 5); + } + CHECK(v2[0] == (std::numeric_limits::min)()); + CHECK(v2[1] == 0); + CHECK(v2[2] == 1); + CHECK(v2[3] == 123); + CHECK(v2[4] == 1000); + if (tc_.has_full_unsigned_type_support() && tc_.has_full_uint64_support()) + { + CHECK(v2[5] == (std::numeric_limits::max)()); + } + } + SECTION("double") { std::vector v; @@ -2389,7 +3014,7 @@ TEST_CASE_METHOD(common_tests, "Dynamic row binding", "[core][dynamic]") CHECK(r.size() == 5); CHECK(r.get_properties(0).get_data_type() == dt_double); - CHECK(r.get_properties(1).get_data_type() == dt_integer); + CHECK(r.get_properties(1).get_data_type() == dt_int32); CHECK(r.get_properties(2).get_data_type() == dt_string); CHECK(r.get_properties(3).get_data_type() == dt_date); @@ -2397,7 +3022,7 @@ TEST_CASE_METHOD(common_tests, "Dynamic row binding", "[core][dynamic]") // - to comply with the implementation for Oracle CHECK(r.get_properties(4).get_data_type() == dt_string); - CHECK(r.get_properties("NUM_INT").get_data_type() == dt_integer); + CHECK(r.get_properties("NUM_INT").get_data_type() == dt_int32); CHECK(r.get_properties(0).get_name() == "NUM_FLOAT"); CHECK(r.get_properties(1).get_name() == "NUM_INT"); @@ -2463,7 +3088,7 @@ TEST_CASE_METHOD(common_tests, "Dynamic row binding", "[core][dynamic]") CHECK(r.size() == 5); CHECK(r.get_properties(0).get_data_type() == dt_double); - CHECK(r.get_properties(1).get_data_type() == dt_integer); + CHECK(r.get_properties(1).get_data_type() == dt_int32); CHECK(r.get_properties(2).get_data_type() == dt_string); CHECK(r.get_properties(3).get_data_type() == dt_date); @@ -2472,7 +3097,7 @@ TEST_CASE_METHOD(common_tests, "Dynamic row binding", "[core][dynamic]") CHECK(r.size() == 2); CHECK(r.get_properties(0).get_data_type() == dt_string); - CHECK(r.get_properties(1).get_data_type() == dt_integer); + CHECK(r.get_properties(1).get_data_type() == dt_int32); // Check if row object is movable row moved = std::move(r); @@ -2482,7 +3107,7 @@ TEST_CASE_METHOD(common_tests, "Dynamic row binding", "[core][dynamic]") CHECK(r.size() == 0); CHECK(moved.get_properties(0).get_data_type() == dt_string); - CHECK(moved.get_properties(1).get_data_type() == dt_integer); + CHECK(moved.get_properties(1).get_data_type() == dt_int32); } } @@ -2503,7 +3128,7 @@ TEST_CASE_METHOD(common_tests, "Dynamic row binding 2", "[core][dynamic]") sql << "select val from soci_test where id = :id", use(id), into(r); CHECK(r.size() == 1); - CHECK(r.get_properties(0).get_data_type() == dt_integer); + CHECK(r.get_properties(0).get_data_type() == dt_int32); CHECK(r.get(0) == 20); } { @@ -2515,19 +3140,19 @@ TEST_CASE_METHOD(common_tests, "Dynamic row binding 2", "[core][dynamic]") id = 2; st.execute(true); CHECK(r.size() == 1); - CHECK(r.get_properties(0).get_data_type() == dt_integer); + CHECK(r.get_properties(0).get_data_type() == dt_int32); CHECK(r.get(0) == 20); id = 3; st.execute(true); CHECK(r.size() == 1); - CHECK(r.get_properties(0).get_data_type() == dt_integer); + CHECK(r.get_properties(0).get_data_type() == dt_int32); CHECK(r.get(0) == 30); id = 1; st.execute(true); CHECK(r.size() == 1); - CHECK(r.get_properties(0).get_data_type() == dt_integer); + CHECK(r.get_properties(0).get_data_type() == dt_int32); CHECK(r.get(0) == 10); } } @@ -2952,11 +3577,11 @@ TEST_CASE_METHOD(common_tests, "Reading rows from rowset", "[core][row][rowset]" // Properties CHECK(r1.size() == 5); CHECK(r1.get_properties(0).get_data_type() == dt_double); - CHECK(r1.get_properties(1).get_data_type() == dt_integer); + CHECK(r1.get_properties(1).get_data_type() == dt_int32); CHECK(r1.get_properties(2).get_data_type() == dt_string); CHECK(r1.get_properties(3).get_data_type() == dt_date); CHECK(r1.get_properties(4).get_data_type() == dt_string); - CHECK(r1.get_properties("NUM_INT").get_data_type() == dt_integer); + CHECK(r1.get_properties("NUM_INT").get_data_type() == dt_int32); // Data @@ -3015,11 +3640,11 @@ TEST_CASE_METHOD(common_tests, "Reading rows from rowset", "[core][row][rowset]" // Properties CHECK(r2.size() == 5); CHECK(r2.get_properties(0).get_data_type() == dt_double); - CHECK(r2.get_properties(1).get_data_type() == dt_integer); + CHECK(r2.get_properties(1).get_data_type() == dt_int32); CHECK(r2.get_properties(2).get_data_type() == dt_string); CHECK(r2.get_properties(3).get_data_type() == dt_date); CHECK(r2.get_properties(4).get_data_type() == dt_string); - CHECK(r2.get_properties("NUM_INT").get_data_type() == dt_integer); + CHECK(r2.get_properties("NUM_INT").get_data_type() == dt_int32); std::string newName = r2.get(2); CHECK(name != newName); @@ -3077,7 +3702,7 @@ TEST_CASE_METHOD(common_tests, "Reading rows from rowset", "[core][row][rowset]" // Properties CHECK(r1.size() == 5); - CHECK(r1.get_properties(0).get_data_type() == dt_integer); + CHECK(r1.get_properties(0).get_data_type() == dt_int32); CHECK(r1.get_properties(1).get_data_type() == dt_double); CHECK(r1.get_properties(2).get_data_type() == dt_string); CHECK(r1.get_properties(3).get_data_type() == dt_date); @@ -3426,8 +4051,8 @@ TEST_CASE_METHOD(common_tests, "NULL with optional", "[core][boost][null]") // for the id column - that's why the code below skips this column // and tests the remaining column only. - //CHECK(r1.get_properties(0).get_data_type() == dt_integer); - CHECK(r1.get_properties(1).get_data_type() == dt_integer); + //CHECK(r1.get_properties(0).get_data_type() == dt_int32); + CHECK(r1.get_properties(1).get_data_type() == dt_int32); CHECK(r1.get_properties(2).get_data_type() == dt_string); //CHECK(r1.get(0) == 1); CHECK(r1.get(1) == 5); @@ -3443,8 +4068,8 @@ TEST_CASE_METHOD(common_tests, "NULL with optional", "[core][boost][null]") CHECK(r2.size() == 3); - // CHECK(r2.get_properties(0).get_data_type() == dt_integer); - CHECK(r2.get_properties(1).get_data_type() == dt_integer); + // CHECK(r2.get_properties(0).get_data_type() == dt_int32); + CHECK(r2.get_properties(1).get_data_type() == dt_int32); CHECK(r2.get_properties(2).get_data_type() == dt_string); //CHECK(r2.get(0) == 2); try From 8544cab99d5c23718c306e7ab7540c7e58034c0d Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Tue, 5 Apr 2022 23:12:15 +0200 Subject: [PATCH 11/46] Update unit tests of MySQL backend for complete integer type support --- tests/mysql/test-mysql.cpp | 22 +++++++++++----------- tests/mysql/test-mysql.h | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/mysql/test-mysql.cpp b/tests/mysql/test-mysql.cpp index 32af3ad7c..c6f39dcef 100644 --- a/tests/mysql/test-mysql.cpp +++ b/tests/mysql/test-mysql.cpp @@ -22,6 +22,7 @@ #include #include #include +#include std::string connectString; backend_factory const &backEnd = *soci::factory_mysql(); @@ -687,9 +688,8 @@ TEST_CASE("MySQL tinyint", "[mysql][int][tinyint]") row r; sql << "select val from soci_test", into(r); REQUIRE(r.size() == 1); - CHECK(r.get_properties("val").get_data_type() == dt_long_long); - CHECK(r.get("val") == 0xffffff00); - CHECK(r.get("val") == 0xffffff00); + CHECK(r.get_properties("val").get_data_type() == dt_uint32); + CHECK(r.get("val") == 0xffffff00); } { soci::session sql(backEnd, connectString); @@ -698,8 +698,8 @@ TEST_CASE("MySQL tinyint", "[mysql][int][tinyint]") row r; sql << "select val from soci_test", into(r); REQUIRE(r.size() == 1); - CHECK(r.get_properties("val").get_data_type() == dt_integer); - CHECK(r.get("val") == -123); + CHECK(r.get_properties("val").get_data_type() == dt_int8); + CHECK(r.get("val") == -123); } { soci::session sql(backEnd, connectString); @@ -708,8 +708,8 @@ TEST_CASE("MySQL tinyint", "[mysql][int][tinyint]") row r; sql << "select val from soci_test", into(r); REQUIRE(r.size() == 1); - CHECK(r.get_properties("val").get_data_type() == dt_integer); - CHECK(r.get("val") == 123); + CHECK(r.get_properties("val").get_data_type() == dt_uint8); + CHECK(r.get("val") == 123); } { soci::session sql(backEnd, connectString); @@ -718,8 +718,8 @@ TEST_CASE("MySQL tinyint", "[mysql][int][tinyint]") row r; sql << "select val from soci_test", into(r); REQUIRE(r.size() == 1); - CHECK(r.get_properties("val").get_data_type() == dt_unsigned_long_long); - CHECK(r.get("val") == 123456789012345ULL); + CHECK(r.get_properties("val").get_data_type() == dt_uint64); + CHECK(r.get("val") == 123456789012345ULL); } { soci::session sql(backEnd, connectString); @@ -728,8 +728,8 @@ TEST_CASE("MySQL tinyint", "[mysql][int][tinyint]") row r; sql << "select val from soci_test", into(r); REQUIRE(r.size() == 1); - CHECK(r.get_properties("val").get_data_type() == dt_long_long); - CHECK(r.get("val") == -123456789012345LL); + CHECK(r.get_properties("val").get_data_type() == dt_int64); + CHECK(r.get("val") == -123456789012345LL); } } diff --git a/tests/mysql/test-mysql.h b/tests/mysql/test-mysql.h index 0fda454b2..8d120c3f8 100644 --- a/tests/mysql/test-mysql.h +++ b/tests/mysql/test-mysql.h @@ -13,8 +13,8 @@ struct table_creator_one : public table_creator_base : table_creator_base(sql) { sql << "create table soci_test(id integer, val integer, c char, " - "str varchar(20), sh int2, ul numeric(20), d float8, " - "num76 numeric(7,6), " + "str varchar(20), sh int2, ll bigint, ul bigint unsigned, " + "d float8, num76 numeric(7,6), " "tm datetime, i1 integer, i2 integer, i3 integer, " "name varchar(20)) engine=InnoDB"; } From 44a4365c6e69c8aa1f5e87ff5d35e11285fff95b Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Thu, 7 Apr 2022 22:25:27 +0200 Subject: [PATCH 12/46] Update unit tests of SQLite3 backend for complete integer type support --- tests/sqlite3/test-sqlite3.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/tests/sqlite3/test-sqlite3.cpp b/tests/sqlite3/test-sqlite3.cpp index dcd34dc10..755959948 100644 --- a/tests/sqlite3/test-sqlite3.cpp +++ b/tests/sqlite3/test-sqlite3.cpp @@ -14,6 +14,7 @@ #include #include #include +#include using namespace soci; using namespace soci::tests; @@ -470,10 +471,10 @@ TEST_CASE("SQLite type inference", "[sqlite][sequence]") row const& r1 = (*it); CHECK(r1.get(0) == cvc); CHECK(r1.get(1) == Approx(cdec)); - CHECK(r1.get(2) == cll); - CHECK(r1.get(3) == cull); - CHECK(r1.get(4) == cll); - CHECK(r1.get(5) == cull); + CHECK(r1.get(2) == cll); + CHECK(r1.get(3) == cull); + CHECK(r1.get(4) == cll); + CHECK(r1.get(5) == cull); } } @@ -548,8 +549,8 @@ struct table_creator_one : public table_creator_base : table_creator_base(sql) { sql << "create table soci_test(id integer, val integer, c char, " - "str varchar(20), sh smallint, ul numeric(20), d float, " - "num76 numeric(7,6), " + "str varchar(20), sh smallint, ll bigint, ul unsigned bigint, " + "d float, num76 numeric(7,6), " "tm datetime, i1 integer, i2 integer, i3 integer, " "name varchar(20))"; } @@ -664,6 +665,11 @@ class test_context : public test_context_base return true; } + bool has_full_uint64_support() const override + { + return false; + } + bool enable_std_char_padding(soci::session&) const override { // SQLite does not support right padded char type. From 236966f2923bd63cd49bf5eb28c5de34e4e6850c Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Tue, 5 Apr 2022 23:12:30 +0200 Subject: [PATCH 13/46] Update unit tests of PostgreSQL backend for complete integer type support --- tests/postgresql/test-postgresql.cpp | 41 ++++++++++++++++------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/tests/postgresql/test-postgresql.cpp b/tests/postgresql/test-postgresql.cpp index fc98f5b79..aed6fbce5 100644 --- a/tests/postgresql/test-postgresql.cpp +++ b/tests/postgresql/test-postgresql.cpp @@ -747,7 +747,7 @@ TEST_CASE("PostgreSQL DDL with metadata", "[postgresql][ddl]") std::string ddl_t3 = "ddl_t3"; // single-expression variant: - sql.create_table(ddl_t1).column("i", soci::dt_integer).column("j", soci::dt_integer); + sql.create_table(ddl_t1).column("i", soci::dt_int32).column("j", soci::dt_int32); // check whether this table was created: @@ -780,13 +780,13 @@ TEST_CASE("PostgreSQL DDL with metadata", "[postgresql][ddl]") { if (ci.name == "i") { - CHECK(ci.type == soci::dt_integer); + CHECK(ci.type == soci::dt_int32); CHECK(ci.nullable); i_found = true; } else if (ci.name == "j") { - CHECK(ci.type == soci::dt_integer); + CHECK(ci.type == soci::dt_int32); CHECK(ci.nullable); j_found = true; } @@ -806,24 +806,24 @@ TEST_CASE("PostgreSQL DDL with metadata", "[postgresql][ddl]") // (note: statement is executed when ddl object goes out of scope) { soci::ddl_type ddl = sql.create_table(ddl_t2); - ddl.column("i", soci::dt_integer); - ddl.column("j", soci::dt_integer); - ddl.column("k", soci::dt_integer)("not null"); + ddl.column("i", soci::dt_int32); + ddl.column("j", soci::dt_int32); + ddl.column("k", soci::dt_int32)("not null"); ddl.primary_key("t2_pk", "j"); } - sql.add_column(ddl_t1, "k", soci::dt_integer); + sql.add_column(ddl_t1, "k", soci::dt_int32); sql.add_column(ddl_t1, "big", soci::dt_string, 0); // "unlimited" length -> text sql.drop_column(ddl_t1, "i"); // or with constraint as in t2: - sql.add_column(ddl_t2, "m", soci::dt_integer)("not null"); + sql.add_column(ddl_t2, "m", soci::dt_int32)("not null"); // third table with a foreign key to the second one { soci::ddl_type ddl = sql.create_table(ddl_t3); - ddl.column("x", soci::dt_integer); - ddl.column("y", soci::dt_integer); + ddl.column("x", soci::dt_int32); + ddl.column("y", soci::dt_int32); ddl.foreign_key("t3_fk", "x", ddl_t2, "j"); } @@ -858,13 +858,13 @@ TEST_CASE("PostgreSQL DDL with metadata", "[postgresql][ddl]") { if (ci.name == "j") { - CHECK(ci.type == soci::dt_integer); + CHECK(ci.type == soci::dt_int32); CHECK(ci.nullable); j_found = true; } else if (ci.name == "k") { - CHECK(ci.type == soci::dt_integer); + CHECK(ci.type == soci::dt_int32); CHECK(ci.nullable); k_found = true; } @@ -899,25 +899,25 @@ TEST_CASE("PostgreSQL DDL with metadata", "[postgresql][ddl]") { if (ci.name == "i") { - CHECK(ci.type == soci::dt_integer); + CHECK(ci.type == soci::dt_int32); CHECK(ci.nullable); i_found = true; } else if (ci.name == "j") { - CHECK(ci.type == soci::dt_integer); + CHECK(ci.type == soci::dt_int32); CHECK(ci.nullable == false); // primary key j_found = true; } else if (ci.name == "k") { - CHECK(ci.type == soci::dt_integer); + CHECK(ci.type == soci::dt_int32); CHECK(ci.nullable == false); k_found = true; } else if (ci.name == "m") { - CHECK(ci.type == soci::dt_integer); + CHECK(ci.type == soci::dt_int32); CHECK(ci.nullable == false); m_found = true; } @@ -1312,8 +1312,8 @@ struct table_creator_one : public table_creator_base : table_creator_base(sql) { sql << "create table soci_test(id integer, val integer, c char, " - "str varchar(20), sh int2, ul numeric(20), d float8, " - "num76 numeric(7,6), " + "str varchar(20), sh int2, ll bigint, ul numeric(20), " + "d float8, num76 numeric(7,6), " "tm timestamp, i1 integer, i2 integer, i3 integer, " "name varchar(20))"; } @@ -1419,6 +1419,11 @@ class test_context : public test_context_base return false; } + bool has_full_uint64_support() const override + { + return false; + } + std::string sql_length(std::string const& s) const override { return "char_length(" + s + ")"; From 0a8f4501b3dfa350dc4bb8004037967a1a884127 Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Tue, 5 Apr 2022 23:12:23 +0200 Subject: [PATCH 14/46] Update unit tests of Oracle backend for complete integer type support --- tests/oracle/test-oracle.cpp | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/tests/oracle/test-oracle.cpp b/tests/oracle/test-oracle.cpp index fcb952e53..75b170b67 100644 --- a/tests/oracle/test-oracle.cpp +++ b/tests/oracle/test-oracle.cpp @@ -1089,7 +1089,7 @@ TEST_CASE("Oracle DDL with metadata", "[oracle][ddl]") std::string ddl_t3 = "DDL_T3"; // single-expression variant: - sql.create_table(ddl_t1).column("I", soci::dt_integer).column("J", soci::dt_integer); + sql.create_table(ddl_t1).column("I", soci::dt_int32).column("J", soci::dt_int32); // check whether this table was created: @@ -1122,13 +1122,13 @@ TEST_CASE("Oracle DDL with metadata", "[oracle][ddl]") { if (ci.name == "I") { - CHECK(ci.type == soci::dt_integer); + CHECK(ci.type == soci::dt_int32); CHECK(ci.nullable); i_found = true; } else if (ci.name == "J") { - CHECK(ci.type == soci::dt_integer); + CHECK(ci.type == soci::dt_int32); CHECK(ci.nullable); j_found = true; } @@ -1148,24 +1148,24 @@ TEST_CASE("Oracle DDL with metadata", "[oracle][ddl]") // (note: statement is executed when ddl object goes out of scope) { soci::ddl_type ddl = sql.create_table(ddl_t2); - ddl.column("I", soci::dt_integer); - ddl.column("J", soci::dt_integer); - ddl.column("K", soci::dt_integer)("not null"); + ddl.column("I", soci::dt_int32); + ddl.column("J", soci::dt_int32); + ddl.column("K", soci::dt_int32)("not null"); ddl.primary_key("t2_pk", "J"); } - sql.add_column(ddl_t1, "K", soci::dt_integer); + sql.add_column(ddl_t1, "K", soci::dt_int32); sql.add_column(ddl_t1, "BIG", soci::dt_string, 0); // "unlimited" length -> CLOB sql.drop_column(ddl_t1, "I"); // or with constraint as in t2: - sql.add_column(ddl_t2, "M", soci::dt_integer)("not null"); + sql.add_column(ddl_t2, "M", soci::dt_int32)("not null"); // third table with a foreign key to the second one { soci::ddl_type ddl = sql.create_table(ddl_t3); - ddl.column("X", soci::dt_integer); - ddl.column("Y", soci::dt_integer); + ddl.column("X", soci::dt_int32); + ddl.column("Y", soci::dt_int32); ddl.foreign_key("t3_fk", "X", ddl_t2, "J"); } @@ -1200,13 +1200,13 @@ TEST_CASE("Oracle DDL with metadata", "[oracle][ddl]") { if (ci.name == "J") { - CHECK(ci.type == soci::dt_integer); + CHECK(ci.type == soci::dt_int32); CHECK(ci.nullable); j_found = true; } else if (ci.name == "K") { - CHECK(ci.type == soci::dt_integer); + CHECK(ci.type == soci::dt_int32); CHECK(ci.nullable); k_found = true; } @@ -1241,25 +1241,25 @@ TEST_CASE("Oracle DDL with metadata", "[oracle][ddl]") { if (ci.name == "I") { - CHECK(ci.type == soci::dt_integer); + CHECK(ci.type == soci::dt_int32); CHECK(ci.nullable); i_found = true; } else if (ci.name == "J") { - CHECK(ci.type == soci::dt_integer); + CHECK(ci.type == soci::dt_int32); CHECK(ci.nullable == false); // primary key j_found = true; } else if (ci.name == "K") { - CHECK(ci.type == soci::dt_integer); + CHECK(ci.type == soci::dt_int32); CHECK(ci.nullable == false); k_found = true; } else if (ci.name == "M") { - CHECK(ci.type == soci::dt_integer); + CHECK(ci.type == soci::dt_int32); CHECK(ci.nullable == false); m_found = true; } @@ -1397,8 +1397,8 @@ struct table_creator_one : public table_creator_base table_creator_one(soci::session & sql) : table_creator_base(sql) { - sql << "create table soci_test(id number(10,0), val number(4,0), c char, " - "str varchar2(20), sh number, ul number, d number, " + sql << "create table soci_test(id number(10,0), val number(8,0), c char, " + "str varchar2(20), sh number, ll number, ul number, d number, " "num76 numeric(7,6), " "tm date, i1 number, i2 number, i3 number, name varchar2(20))"; } From 455a5804a3b36e84309261c44c2849214c1f473c Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Sun, 8 May 2022 18:18:25 +0200 Subject: [PATCH 15/46] Update unit tests of DB2 backend for complete integer type support --- tests/db2/test-db2.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/db2/test-db2.cpp b/tests/db2/test-db2.cpp index fa84241fe..eaeb86df6 100644 --- a/tests/db2/test-db2.cpp +++ b/tests/db2/test-db2.cpp @@ -29,8 +29,8 @@ struct table_creator_one : public table_creator_base table_creator_one(soci::session & sql) : table_creator_base(sql) { - sql << "CREATE TABLE SOCI_TEST(ID INTEGER, VAL SMALLINT, C CHAR, STR VARCHAR(20), SH SMALLINT, UL NUMERIC(20), D DOUBLE, " - "NUM76 NUMERIC(7,6), " + sql << "CREATE TABLE SOCI_TEST(ID INTEGER, VAL SMALLINT, C CHAR, STR VARCHAR(20), SH SMALLINT, LL BIGINT, UL NUMERIC(20), " + "D DOUBLE, NUM76 NUMERIC(7,6), " "TM TIMESTAMP, I1 INTEGER, I2 INTEGER, I3 INTEGER, NAME VARCHAR(20))"; } }; @@ -91,6 +91,11 @@ class test_context :public test_context_base return new table_creator_for_get_affected_rows(s); } + bool has_full_uint64_support() const override + { + return false; + } + std::string to_date_time(std::string const & pi_datdt_string) const override { return "to_date('" + pi_datdt_string + "', 'YYYY-MM-DD HH24:MI:SS')"; From b56224e6a7b796d10d544078b96065f2f6d69ba2 Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Tue, 5 Apr 2022 23:12:07 +0200 Subject: [PATCH 16/46] Update unit test of Firebird backend for complete integer type support --- tests/firebird/test-firebird.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/firebird/test-firebird.cpp b/tests/firebird/test-firebird.cpp index 09c74fa14..fa69a2ab6 100644 --- a/tests/firebird/test-firebird.cpp +++ b/tests/firebird/test-firebird.cpp @@ -772,7 +772,7 @@ TEST_CASE("Firebird dynamic binding", "[firebird][dynamic]") CHECK(r.get_properties(1).get_name() == "MSG"); CHECK(r.get_properties(2).get_name() == "NTEST"); - CHECK(r.get_properties(0).get_data_type() == dt_integer); + CHECK(r.get_properties(0).get_data_type() == dt_int32); CHECK(r.get_properties(1).get_data_type() == dt_string); CHECK(r.get_properties(2).get_data_type() == dt_double); @@ -781,7 +781,7 @@ TEST_CASE("Firebird dynamic binding", "[firebird][dynamic]") CHECK(r.get_properties("MSG").get_name() == "MSG"); CHECK(r.get_properties("NTEST").get_name() == "NTEST"); - CHECK(r.get_properties("ID").get_data_type() == dt_integer); + CHECK(r.get_properties("ID").get_data_type() == dt_int32); CHECK(r.get_properties("MSG").get_data_type() == dt_string); CHECK(r.get_properties("NTEST").get_data_type() == dt_double); @@ -1231,8 +1231,8 @@ struct TableCreator1 : public tests::table_creator_base : tests::table_creator_base(sql) { sql << "create table soci_test(id integer, val integer, c char, " - "str varchar(20), sh smallint, ul bigint, d double precision, " - "num76 numeric(7,6), " + "str varchar(20), sh smallint, ll bigint, ul bigint, " + "d double precision, num76 numeric(7,6), " "tm timestamp, i1 integer, i2 integer, i3 integer, name varchar(20))"; sql.commit(); sql.begin(); @@ -1334,6 +1334,11 @@ class test_context : public tests::test_context_base return new TableCreatorXML(s); } + bool has_full_uint64_support() const override + { + return false; + } + std::string to_date_time(std::string const &datdt_string) const override { return "'" + datdt_string + "'"; From 43ab82fdec7a7d264fbafcbdec64105e430dc84b Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Sun, 8 May 2022 18:18:46 +0200 Subject: [PATCH 17/46] Update unit tests of ODBC backend for complete integer type support --- tests/odbc/test-odbc-access.cpp | 4 ++-- tests/odbc/test-odbc-db2.cpp | 9 ++++++-- tests/odbc/test-odbc-mssql.cpp | 33 +++++++++++++++++++++++++++-- tests/odbc/test-odbc-mysql.cpp | 19 ++++++++++++++++- tests/odbc/test-odbc-postgresql.cpp | 9 ++++++-- 5 files changed, 65 insertions(+), 9 deletions(-) diff --git a/tests/odbc/test-odbc-access.cpp b/tests/odbc/test-odbc-access.cpp index b4ec39870..2783646f4 100644 --- a/tests/odbc/test-odbc-access.cpp +++ b/tests/odbc/test-odbc-access.cpp @@ -26,8 +26,8 @@ struct table_creator_one : public table_creator_base : table_creator_base(sql) { sql << "create table soci_test(id integer, val integer, c char, " - "str varchar(20), sh integer, ul number, d float, " - "num76 numeric(7,6), " + "str varchar(20), sh integer, ll number, ul number, " + "d float, num76 numeric(7,6), " "tm timestamp, i1 integer, i2 integer, i3 integer, " "name varchar(20))"; } diff --git a/tests/odbc/test-odbc-db2.cpp b/tests/odbc/test-odbc-db2.cpp index bcd771d9b..b828cc27f 100644 --- a/tests/odbc/test-odbc-db2.cpp +++ b/tests/odbc/test-odbc-db2.cpp @@ -25,8 +25,8 @@ struct table_creator_one : public table_creator_base table_creator_one(soci::session & sql) : table_creator_base(sql) { - sql << "CREATE TABLE SOCI_TEST(ID INTEGER, VAL SMALLINT, C CHAR, STR VARCHAR(20), SH SMALLINT, UL NUMERIC(20), D DOUBLE, " - "NUM76 NUMERIC(7,6), " + sql << "CREATE TABLE SOCI_TEST(ID INTEGER, VAL SMALLINT, C CHAR, STR VARCHAR(20), SH SMALLINT, LL BIGINT, UL NUMERIC(20), " + "D DOUBLE, NUM76 NUMERIC(7,6), " "TM TIMESTAMP(9), I1 INTEGER, I2 INTEGER, I3 INTEGER, NAME VARCHAR(20))"; } }; @@ -89,6 +89,11 @@ class test_context : public test_context_base return new table_creator_for_get_affected_rows(s); } + bool has_full_uint64_support() const override + { + return false; + } + std::string to_date_time(std::string const &datdt_string) const { return "\'" + datdt_string + "\'"; diff --git a/tests/odbc/test-odbc-mssql.cpp b/tests/odbc/test-odbc-mssql.cpp index 252ac17fe..5d51076b3 100644 --- a/tests/odbc/test-odbc-mssql.cpp +++ b/tests/odbc/test-odbc-mssql.cpp @@ -82,8 +82,8 @@ struct table_creator_one : public table_creator_base : table_creator_base(sql) { sql << "create table soci_test(id integer, val integer, c char, " - "str varchar(20), sh smallint, ul numeric(20), d float, " - "num76 numeric(7,6), " + "str varchar(20), sh smallint, ll bigint, ul numeric(20), " + "d float, num76 numeric(7,6), " "tm datetime, i1 integer, i2 integer, i3 integer, " "name varchar(20))"; } @@ -210,6 +210,35 @@ class test_context : public test_context_base return true; } + bool has_full_int8_support() const override + { + // MS SQL only supports tinyint values in the range [0..255]. + return false; + } + + bool has_full_unsigned_type_support() const override + { + // MS SQL only supports signed integer types. A direct mapping to + // e.g. a uint32 value is therefore only possible up to its equivalent + // signed type range. + // + // In the past, when tests used unsigned types, an overflow happened + // on the C++ side, effectively storing a negative value in the database. + // When reading this value back to an unsigned value, another overflow + // on the C++ side lead to the correct result in the unsigned type var. + // Since SOCI's full support of fixed-size C++ integers and the + // corresponding changes in database communication, unsigned types would + // get stored as-is without any overflows on the C++ side. As MS SQL + // doesn't support unsigned types, we get an overflow and an insertion + // error there. + return false; + } + + bool has_full_uint64_support() const override + { + return has_full_unsigned_type_support(); + } + std::string sql_length(std::string const& s) const override { return "len(" + s + ")"; diff --git a/tests/odbc/test-odbc-mysql.cpp b/tests/odbc/test-odbc-mysql.cpp index 9ea70adf6..bdc67ed36 100644 --- a/tests/odbc/test-odbc-mysql.cpp +++ b/tests/odbc/test-odbc-mysql.cpp @@ -16,6 +16,23 @@ std::string connectString; backend_factory const &backEnd = *soci::factory_odbc(); +class test_context_odbc_mysql : public test_context +{ +public: + test_context_odbc_mysql(backend_factory const &backEnd_, + std::string const &connectString_) + : test_context(backEnd_, connectString_) {} + + bool has_full_uint64_support() const override + { + // For some reason it seems that MySQL has a bug under ODBC with which + // the maximum value of a uint64_t cannot be stored in and retrieved + // from the database. I.e. when storing 18446744073709551615, you're + // retrieving the value 9223372036854775807. + return false; + } +}; + int main(int argc, char** argv) { #ifdef _MSC_VER @@ -43,7 +60,7 @@ int main(int argc, char** argv) connectString = "FILEDSN=./test-mysql.dsn"; } - test_context tc(backEnd, connectString); + test_context_odbc_mysql tc(backEnd, connectString); return Catch::Session().run(argc, argv); } diff --git a/tests/odbc/test-odbc-postgresql.cpp b/tests/odbc/test-odbc-postgresql.cpp index 64da86861..1fcf628e7 100644 --- a/tests/odbc/test-odbc-postgresql.cpp +++ b/tests/odbc/test-odbc-postgresql.cpp @@ -92,8 +92,8 @@ struct table_creator_one : public table_creator_base : table_creator_base(sql) { sql << "create table soci_test(id integer, val integer, c char, " - "str varchar(20), sh int2, ul numeric(20), d float8, " - "num76 numeric(7,6), " + "str varchar(20), sh int2, ll bigint, ul numeric(20), " + "d float8, num76 numeric(7,6), " "tm timestamp, i1 integer, i2 integer, i3 integer, " "name varchar(20))"; } @@ -212,6 +212,11 @@ class test_context : public test_context_base return !m_verDriver.is_initialized() || m_verDriver < odbc_version(9, 3, 400); } + bool has_full_uint64_support() const override + { + return false; + } + std::string fix_crlf_if_necessary(std::string const& s) const override { // Version 9.03.0300 (ancient, but still used on AppVeyor CI) is known From 71d9b8750b0c8702d9d84651d2a1beb7f852f2d2 Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Sat, 18 Jun 2022 18:24:42 +0200 Subject: [PATCH 18/46] Add *_int and *_long_long methods back to the soci-simple API To stay backwards-compatible as much as possible, we should keep all methods from the soci-simple API and just forward them to their new equivalents. --- include/soci/soci-simple.h | 215 ++++++++++++++++++++----------------- src/core/soci-simple.cpp | 94 +++++++++++++++- 2 files changed, 210 insertions(+), 99 deletions(-) diff --git a/include/soci/soci-simple.h b/include/soci/soci-simple.h index 785d2f7db..203adbe90 100644 --- a/include/soci/soci-simple.h +++ b/include/soci/soci-simple.h @@ -58,108 +58,121 @@ 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_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); +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_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); +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 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); +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 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); +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_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); +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_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); - +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_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); +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); @@ -170,6 +183,10 @@ 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, @@ -193,19 +210,21 @@ SOCI_DECL void soci_set_use_date_v(statement_handle st, // 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 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); +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 diff --git a/src/core/soci-simple.cpp b/src/core/soci-simple.cpp index be7820909..834f89a5a 100644 --- a/src/core/soci-simple.cpp +++ b/src/core/soci-simple.cpp @@ -942,6 +942,16 @@ SOCI_DECL int soci_into_string(statement_handle st) return wrapper->next_position++; } +SOCI_DECL int soci_into_int(statement_handle st) +{ + return soci_into_int32(st); +} + +SOCI_DECL int soci_into_long_long(statement_handle st) +{ + return soci_into_int64(st); +} + SOCI_DECL int soci_into_int8(statement_handle st) { statement_wrapper * wrapper = static_cast(st); @@ -1158,6 +1168,16 @@ SOCI_DECL int soci_into_string_v(statement_handle st) return wrapper->next_position++; } +SOCI_DECL int soci_into_int_v(statement_handle st) +{ + return soci_into_int32_v(st); +} + +SOCI_DECL int soci_into_long_long_v(statement_handle st) +{ + return soci_into_int64_v(st); +} + SOCI_DECL int soci_into_int8_v(statement_handle st) { statement_wrapper * wrapper = static_cast(st); @@ -1367,6 +1387,16 @@ SOCI_DECL char const * soci_get_into_string(statement_handle st, int position) return wrapper->into_strings[position].c_str(); } +SOCI_DECL int soci_get_into_int(statement_handle st, int position) +{ + return static_cast(soci_get_into_int32(st, position)); +} + +SOCI_DECL long long soci_get_into_long_long(statement_handle st, int position) +{ + return static_cast(soci_get_into_int64(st, position)); +} + SOCI_DECL int8_t soci_get_into_int8(statement_handle st, int position) { statement_wrapper * wrapper = static_cast(st); @@ -1644,6 +1674,16 @@ SOCI_DECL char const * soci_get_into_string_v(statement_handle st, int position, return v[index].c_str(); } +SOCI_DECL int soci_get_into_int_v(statement_handle st, int position, int index) +{ + return static_cast(soci_get_into_int32_v(st, position, index)); +} + +SOCI_DECL long long soci_get_into_long_long_v(statement_handle st, int position, int index) +{ + return static_cast(soci_get_into_int64_v(st, position, index)); +} + SOCI_DECL int8_t soci_get_into_int8_v(statement_handle st, int position, int index) { statement_wrapper * wrapper = static_cast(st); @@ -1861,6 +1901,16 @@ SOCI_DECL void soci_use_string(statement_handle st, char const * name) wrapper->use_strings[name]; // create new entry } +SOCI_DECL void soci_use_int(statement_handle st, char const * name) +{ + soci_use_int32(st, name); +} + +SOCI_DECL void soci_use_long_long(statement_handle st, char const * name) +{ + soci_use_int64(st, name); +} + SOCI_DECL void soci_use_int8(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); @@ -2065,6 +2115,16 @@ SOCI_DECL void soci_use_string_v(statement_handle st, char const * name) wrapper->use_strings_v[name]; // create new entry } +SOCI_DECL void soci_use_int_v(statement_handle st, char const * name) +{ + soci_use_int32_v(st, name); +} + +SOCI_DECL void soci_use_long_long_v(statement_handle st, char const * name) +{ + soci_use_int64_v(st, name); +} + SOCI_DECL void soci_use_int8_v(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); @@ -2266,6 +2326,16 @@ SOCI_DECL void soci_set_use_string(statement_handle st, char const * name, char wrapper->use_strings[name] = val; } +SOCI_DECL void soci_set_use_int(statement_handle st, char const * name, int32_t val) +{ + soci_set_use_int32(st, name, static_cast(val)); +} + +SOCI_DECL void soci_set_use_long_long(statement_handle st, char const * name, long long val) +{ + soci_set_use_int64(st, name, static_cast(val)); +} + SOCI_DECL void soci_set_use_int8(statement_handle st, char const * name, int8_t val) { statement_wrapper * wrapper = static_cast(st); @@ -2531,6 +2601,18 @@ SOCI_DECL void soci_set_use_string_v(statement_handle st, v[index] = val; } +SOCI_DECL void soci_set_use_int_v(statement_handle st, + char const * name, int index, int val) +{ + soci_set_use_int32_v(st, name, index, static_cast(val)); +} + +SOCI_DECL void soci_set_use_long_long_v(statement_handle st, + char const * name, int index, long long val) +{ + soci_set_use_int64_v(st, name, index, static_cast(val)); +} + SOCI_DECL void soci_set_use_int8_v(statement_handle st, char const * name, int index, int8_t val) { @@ -2778,6 +2860,16 @@ SOCI_DECL char const * soci_get_use_string(statement_handle st, char const * nam return wrapper->use_strings[name].c_str(); } +SOCI_DECL int soci_get_use_int(statement_handle st, char const * name) +{ + return static_cast(soci_get_use_int32(st, name)); +} + +SOCI_DECL long long soci_get_use_long_long(statement_handle st, char const * name) +{ + return static_cast(soci_get_use_int64(st, name)); +} + SOCI_DECL int8_t soci_get_use_int8(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); @@ -3215,7 +3307,7 @@ SOCI_DECL void soci_prepare(statement_handle st, char const * query) } } - // bind all use vecctor elements + // bind all use vector elements { // strings typedef std::map Date: Sat, 18 Jun 2022 23:27:29 +0200 Subject: [PATCH 19/46] Update docs for complete integer type support --- docs/api/backend.md | 31 +++++++++++++--- docs/api/client.md | 74 ++++++++++++++++++++++++++++++++++++- docs/backends/firebird.md | 18 +++++---- docs/backends/mysql.md | 24 +++++++----- docs/backends/odbc.md | 16 +++++--- docs/backends/oracle.md | 14 +++---- docs/backends/postgresql.md | 17 +++++---- docs/backends/sqlite3.md | 18 +++++---- docs/interfaces.md | 4 +- docs/types.md | 66 ++++++++++++++++++++++++--------- docs/utilities.md | 16 ++++---- 11 files changed, 218 insertions(+), 80 deletions(-) diff --git a/docs/api/backend.md b/docs/api/backend.md index bf99ad242..3041ba3cd 100644 --- a/docs/api/backend.md +++ b/docs/api/backend.md @@ -21,7 +21,19 @@ All names are defined in either `soci` or `soci::details` namespace. // data types, as seen by the user enum data_type { - dt_string, dt_date, dt_double, dt_integer, dt_long_long, dt_unsigned_long_long + dt_string, + dt_int8, + dt_uint8, + dt_int16, + dt_uint16, + dt_int32, + dt_uint32, + dt_int64, + dt_uint64, + dt_double, + dt_date, + dt_blob, + dt_xml }; // the enum type for indicator variables @@ -32,15 +44,22 @@ enum exchange_type { x_char, x_stdstring, - x_short, - x_integer, - x_long_long, - x_unsigned_long_long, + 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_blob, + + x_xmltype, + x_longstring }; struct cstring_descriptor diff --git a/docs/api/client.md b/docs/api/client.md index b149c04bc..febfdf9e2 100644 --- a/docs/api/client.md +++ b/docs/api/client.md @@ -13,7 +13,7 @@ The following types are commonly used in the rest of the interface: ```cpp // data types, as seen by the user -enum data_type { dt_string, dt_date, dt_double, dt_integer, dt_long_long, dt_unsigned_long_long }; +enum data_type { dt_string, dt_date, dt_double, dt_int8, dt_uint8, dt_int16, dt_uint16, dt_int32, dt_uint32, dt_int64, dt_uint64 }; // the enum type for indicator variables enum indicator { i_ok, i_null, i_truncated }; @@ -642,6 +642,14 @@ The functions above create and destroy the statement object. If the statement ca int soci_into_string (statement_handle st); int soci_into_int (statement_handle st); int soci_into_long_long(statement_handle st); +int soci_into_int8 (statement_handle st); +int soci_into_uint8 (statement_handle st); +int soci_into_int16 (statement_handle st); +int soci_into_uint16 (statement_handle st); +int soci_into_int32 (statement_handle st); +int soci_into_uint32 (statement_handle st); +int soci_into_int64 (statement_handle st); +int soci_into_uint64 (statement_handle st); int soci_into_double (statement_handle st); int soci_into_date (statement_handle st); int soci_into_blob (statement_handle st); @@ -649,6 +657,14 @@ int soci_into_blob (statement_handle st); int soci_into_string_v (statement_handle st); int soci_into_int_v (statement_handle st); int soci_into_long_long_v(statement_handle st); +int soci_into_int8_v (statement_handle st); +int soci_into_uint8_v (statement_handle st); +int soci_into_int16_v (statement_handle st); +int soci_into_uint16_v (statement_handle st); +int soci_into_int32_v (statement_handle st); +int soci_into_uint32_v (statement_handle st); +int soci_into_int64_v (statement_handle st); +int soci_into_uint64_v (statement_handle st); int soci_into_double_v (statement_handle st); int soci_into_date_v (statement_handle st); ``` @@ -669,6 +685,14 @@ This function returns `1` if the into element at the given position has non-null char const * soci_get_into_string (statement_handle st, int position); int soci_get_into_int (statement_handle st, int position); long long soci_get_into_long_long(statement_handle st, int position); +int8_t soci_get_into_int8 (statement_handle st, int position); +uint8_t soci_get_into_uint8 (statement_handle st, int position); +int16_t soci_get_into_int16 (statement_handle st, int position); +uint16_t soci_get_into_uint16 (statement_handle st, int position); +int32_t soci_get_into_int32 (statement_handle st, int position); +uint32_t soci_get_into_uint32 (statement_handle st, int position); +int64_t soci_get_into_int64 (statement_handle st, int position); +uint64_t soci_get_into_uint64 (statement_handle st, int position); double soci_get_into_double (statement_handle st, int position); char const * soci_get_into_date (statement_handle st, int position); blob_handle soci_get_into_blob (statement_handle st, int position); @@ -676,6 +700,14 @@ blob_handle soci_get_into_blob (statement_handle st, int position); char const * soci_get_into_string_v (statement_handle st, int position, int index); int soci_get_into_int_v (statement_handle st, int position, int index); long long soci_get_into_long_long_v(statement_handle st, int position, int index); +int8_t soci_get_into_int8_v (statement_handle st, int position, int index); +uint8_t soci_get_into_uint8_v (statement_handle st, int position, int index); +int16_t soci_get_into_int16_v (statement_handle st, int position, int index); +uint16_t soci_get_into_uint16_v (statement_handle st, int position, int index); +int32_t soci_get_into_int32_v (statement_handle st, int position, int index); +uint32_t soci_get_into_uint32_v (statement_handle st, int position, int index); +int64_t soci_get_into_int64_v (statement_handle st, int position, int index); +uint64_t soci_get_into_uint64_v (statement_handle st, int position, int index); double soci_get_into_double_v (statement_handle st, int position, int index); char const * soci_get_into_date_v (statement_handle st, int position, int index); ``` @@ -688,6 +720,14 @@ The functions above allow to retrieve the current value of the given into elemen void soci_use_string (statement_handle st, char const * name); void soci_use_int (statement_handle st, char const * name); void soci_use_long_long(statement_handle st, char const * name); +void soci_use_int8 (statement_handle st, char const * name); +void soci_use_uint8 (statement_handle st, char const * name); +void soci_use_int16 (statement_handle st, char const * name); +void soci_use_uint16 (statement_handle st, char const * name); +void soci_use_int32 (statement_handle st, char const * name); +void soci_use_uint32 (statement_handle st, char const * name); +void soci_use_int64 (statement_handle st, char const * name); +void soci_use_uint64 (statement_handle st, char const * name); void soci_use_double (statement_handle st, char const * name); void soci_use_date (statement_handle st, char const * name); void soci_use_blob (statement_handle st, char const * name); @@ -695,6 +735,14 @@ void soci_use_blob (statement_handle st, char const * name); void soci_use_string_v (statement_handle st, char const * name); void soci_use_int_v (statement_handle st, char const * name); void soci_use_long_long_v(statement_handle st, char const * name); +void soci_use_int8_v (statement_handle st, char const * name); +void soci_use_uint8_v (statement_handle st, char const * name); +void soci_use_int16_v (statement_handle st, char const * name); +void soci_use_uint16_v (statement_handle st, char const * name); +void soci_use_int32_v (statement_handle st, char const * name); +void soci_use_uint32_v (statement_handle st, char const * name); +void soci_use_int64_v (statement_handle st, char const * name); +void soci_use_uint64_v (statement_handle st, char const * name); void soci_use_double_v (statement_handle st, char const * name); void soci_use_date_v (statement_handle st, char const * name); ``` @@ -718,6 +766,14 @@ These functions get and set the size of vector use elements (see comments for ve void soci_set_use_string (statement_handle st, char const * name, char const * val); void soci_set_use_int (statement_handle st, char const * name, int val); void soci_set_use_long_long(statement_handle st, char const * name, long long val); +void soci_set_use_int8 (statement_handle st, char const * name, int8_t val); +void soci_set_use_uint8 (statement_handle st, char const * name, uint8_t val); +void soci_set_use_int16 (statement_handle st, char const * name, int16_t val); +void soci_set_use_uint16 (statement_handle st, char const * name, uint16_t val); +void soci_set_use_int32 (statement_handle st, char const * name, int32_t val); +void soci_set_use_uint32 (statement_handle st, char const * name, uint32_t val); +void soci_set_use_int64 (statement_handle st, char const * name, int64_t val); +void soci_set_use_uint64 (statement_handle st, char const * name, uint64_t val); void soci_set_use_double (statement_handle st, char const * name, double val); void soci_set_use_date (statement_handle st, char const * name, char const * val); void soci_set_use_blob (statement_handle st, char const * name, blob_handle blob); @@ -726,6 +782,14 @@ void soci_set_use_state_v (statement_handle st, char const * name, int index, void soci_set_use_string_v (statement_handle st, char const * name, int index, char const * val); void soci_set_use_int_v (statement_handle st, char const * name, int index, int val); void soci_set_use_long_long_v(statement_handle st, char const * name, int index, long long val); +void soci_set_use_int8_v (statement_handle st, char const * name, int index, int8_t val); +void soci_set_use_uint8_v (statement_handle st, char const * name, int index, uint8_t val); +void soci_set_use_int16_v (statement_handle st, char const * name, int index, int16_t val); +void soci_set_use_uint16_v (statement_handle st, char const * name, int index, uint16_t val); +void soci_set_use_int32_v (statement_handle st, char const * name, int index, int32_t val); +void soci_set_use_uint32_v (statement_handle st, char const * name, int index, uint32_t val); +void soci_set_use_int64_v (statement_handle st, char const * name, int index, int64_t val); +void soci_set_use_uint64_v (statement_handle st, char const * name, int index, uint64_t val); void soci_set_use_double_v (statement_handle st, char const * name, int index, double val); void soci_set_use_date_v (statement_handle st, char const * name, int index, char const * val); ``` @@ -739,6 +803,14 @@ int soci_get_use_state (statement_handle st, char const * name); char const * soci_get_use_string (statement_handle st, char const * name); int soci_get_use_int (statement_handle st, char const * name); long long soci_get_use_long_long(statement_handle st, char const * name); +int8_t soci_get_use_int8 (statement_handle st, char const * name); +uint8_t soci_get_use_uint8 (statement_handle st, char const * name); +int16_t soci_get_use_int16 (statement_handle st, char const * name); +uint16_t soci_get_use_uint16 (statement_handle st, char const * name); +int32_t soci_get_use_int32 (statement_handle st, char const * name); +uint32_t soci_get_use_uint32 (statement_handle st, char const * name); +int64_t soci_get_use_int64 (statement_handle st, char const * name); +uint64_t soci_get_use_uint64 (statement_handle st, char const * name); double soci_get_use_double (statement_handle st, char const * name); char const * soci_get_use_date (statement_handle st, char const * name); blob_handle soci_get_use_blob (statement_handle st, char const * name); diff --git a/docs/backends/firebird.md b/docs/backends/firebird.md index 24e26111e..ddb302463 100644 --- a/docs/backends/firebird.md +++ b/docs/backends/firebird.md @@ -73,14 +73,16 @@ type is not known at compile time. When calling `row::get()`, the type you should pass as T depends upon the underlying database type. For the Firebird backend, this type mapping is: -|Firebird Data Type|SOCI Data Type|`row::get` specializations| -|--- |--- |--- | -|numeric, decimal (where scale > 0)|dt_double|double| -|numeric, decimal [^1] (where scale = 0)|dt_integer, dt_double|int, double| -|double precision, float|dt_double|double| -|smallint, integer|dt_integer|int| -|char, varchar|dt_string|std::string| -|date, time, timestamp|dt_date|std::tm| +| Firebird Data Type | SOCI Data Type | `row::get` specializations | +| --------------------------------------- | --------------------------------------- | --------------------------------- | +| numeric, decimal (where scale > 0) | dt_double | double | +| numeric, decimal [^1] (where scale = 0) | dt_int16/dt_int32/dt_int64, dt_double | dt_int16/int32_t/dt_int64, double | +| double precision, float | dt_double | double | +| smallint | dt_int16 | int16_t | +| integer | dt_int32 | int32_t | +| bigint | dt_int64 | int64_t | +| char, varchar | dt_string | std::string | +| date, time, timestamp | dt_date | std::tm | [^1] There is also 64bit integer type for larger values which is currently not supported. diff --git a/docs/backends/mysql.md b/docs/backends/mysql.md index 7589718dc..c89de9be2 100644 --- a/docs/backends/mysql.md +++ b/docs/backends/mysql.md @@ -72,15 +72,21 @@ The MySQL backend supports the use of the SOCI `row` class, which facilitates re When calling `row::get()`, the type you should pass as `T` depends upon the underlying database type. For the MySQL backend, this type mapping is: -|MySQL Data Type|SOCI Data Type|`row::get` specializations| -|--- |--- |--- | -|FLOAT, DOUBLE, DECIMAL and synonyms|dt_double|double| -|TINYINT, TINYINT UNSIGNED, SMALLINT, SMALLINT UNSIGNED, INT|dt_integer|int| -|INT UNSIGNED|dt_long_long|long long or unsigned| -|BIGINT|dt_long_long|long long| -|BIGINT UNSIGNED|dt_unsigned_long_long|unsigned long long| -|CHAR, VARCHAR, BINARY, VARBINARY, TINYBLOB, MEDIUMBLOB, BLOB,LONGBLOB, TINYTEXT, MEDIUMTEXT, TEXT, LONGTEXT, ENUM|dt_string|std::string| -|TIMESTAMP (works only with MySQL >= 5.0), DATE, TIME, DATETIME|dt_date|std::tm| +| MySQL Data Type | SOCI Data Type | `row::get` specializations | +| ----------------------------------------------------------------------------------------------------------------- | --------------------- | ----------------------------- | +| FLOAT, DOUBLE, DECIMAL and synonyms | dt_double | double | +| TINYINT | dt_int8 | int8_t | +| TINYINT UNSIGNED | dt_uint8 | uint8_t | +| SMALLINT | dt_int16 | int16_t | +| SMALLINT UNSIGNED | dt_uint16 | uint16_t | +| MEDIUMINT | dt_int32 | int32_t | +| MEDIUMINT UNSIGNED | dt_uint32 | uint32_t | +| INT | dt_int32 | int32_t | +| INT UNSIGNED | dt_uint32 | uint32_t | +| BIGINT | dt_int64 | int64_t | +| BIGINT UNSIGNED | dt_uint64 | uint64_t | +| CHAR, VARCHAR, BINARY, VARBINARY, TINYBLOB, MEDIUMBLOB, BLOB,LONGBLOB, TINYTEXT, MEDIUMTEXT, TEXT, LONGTEXT, ENUM | dt_string | std::string | +| TIMESTAMP (works only with MySQL >= 5.0), DATE, TIME, DATETIME | dt_date | std::tm | (See the [dynamic resultset binding](../types.md#dynamic-binding) documentation for general information on using the `Row` class.) diff --git a/docs/backends/odbc.md b/docs/backends/odbc.md index 84bcd38f6..13f9e46df 100644 --- a/docs/backends/odbc.md +++ b/docs/backends/odbc.md @@ -60,14 +60,18 @@ The ODBC backend supports the use of the SOCI `row` class, which facilitates ret When calling `row::get()`, the type you should pass as T depends upon the underlying database type. For the ODBC backend, this type mapping is: -|ODBC Data Type|SOCI Data Type|`row::get` specializations| -|--- |--- |--- | -|SQL_DOUBLE, SQL_DECIMAL, SQL_REAL, SQL_FLOAT, SQL_NUMERIC|dt_double|double| -|SQL_TINYINT, SQL_SMALLINT, SQL_INTEGER, SQL_BIGINT|dt_integer|int| -|SQL_CHAR, SQL_VARCHAR|dt_string|std::string| -|SQL_TYPE_DATE, SQL_TYPE_TIME, SQL_TYPE_TIMESTAMP|dt_date|std::tm| +| ODBC Data Type | SOCI Data Type | `row::get` specializations | +| --------------------------------------------------------- | -------------- | ----------------------------- | +| SQL_DOUBLE, SQL_DECIMAL, SQL_REAL, SQL_FLOAT, SQL_NUMERIC | dt_double | double | +| SQL_TINYINT | dt_int8 | int8_t | +| SQL_SMALLINT | dt_int16 | int16_t | +| SQL_INTEGER | dt_int32 | int32_t | +| SQL_BIGINT | dt_int64 | int64_t | +| SQL_CHAR, SQL_VARCHAR | dt_string | std::string | +| SQL_TYPE_DATE, SQL_TYPE_TIME, SQL_TYPE_TIMESTAMP | dt_date | std::tm | Not all ODBC drivers support all datatypes. +Columns having the attribute `unsigned` get mapped to their corresponding `dt_uint[n]` and `uint[n]_t` types. (See the [dynamic resultset binding](../types.md#dynamic-binding) documentation for general information on using the `row` class.) diff --git a/docs/backends/oracle.md b/docs/backends/oracle.md index 4e5eae434..7eeec47c6 100644 --- a/docs/backends/oracle.md +++ b/docs/backends/oracle.md @@ -71,13 +71,13 @@ The Oracle backend supports the use of the SOCI `row` class, which facilitates r When calling `row::get()`, the type you should pass as `T` depends upon the underlying database type. For the Oracle backend, this type mapping is: -|Oracle Data Type|SOCI Data Type|`row::get` specializations| -|--- |--- |--- | -|number (where scale > 0)|dt_double|double| -|number(where scale = 0 and precision ≤ `std::numeric_limits::digits10`)|dt_integer|int| -|number|dt_long_long|long long| -|char, varchar, varchar2|dt_string|std::string| -|date|dt_date|std::tm| +| Oracle Data Type | SOCI Data Type | `row::get` specializations | +| --------------------------------------------------------------------------------- | -------------- | ----------------------------- | +| number (where scale > 0) | dt_double | double | +| number (where scale = 0 and precision ≤ `std::numeric_limits::digits10`) | dt_int32 | int32_t | +| number (where scale = 0) | dt_int64 | int64_t | +| char, varchar, varchar2 | dt_string | std::string | +| date | dt_date | std::tm | (See the [dynamic resultset binding](../types.md#dynamic-binding) documentation for general information on using the `row` class.) diff --git a/docs/backends/postgresql.md b/docs/backends/postgresql.md index 5f97f7f92..30682a541 100644 --- a/docs/backends/postgresql.md +++ b/docs/backends/postgresql.md @@ -88,14 +88,15 @@ The PostgreSQL backend supports the use of the SOCI `row` class, which facilitat When calling `row::get()`, the type you should pass as `T` depends upon the underlying database type. For the PostgreSQL backend, this type mapping is: -|PostgreSQL Data Type|SOCI Data Type|`row::get` specializations| -|--- |--- |--- | -|numeric, real, double|dt_double|double| -|boolean, smallint, integer|dt_integer|int| -|int8|dt_long_long|long long| -|oid|dt_integer|unsigned long| -|char, varchar, text, cstring, bpchar|dt_string|std::string| -|abstime, reltime, date, time, timestamp, timestamptz, timetz|dt_date|std::tm| +| PostgreSQL Data Type | SOCI Data Type | `row::get` specializations | +| ------------------------------------------------------------ | -------------- | ----------------------------- | +| numeric, real, double | dt_double | double | +| smallint | dt_int16 | int16_t | +| boolean, integer | dt_int32 | int32_t | +| int8 | dt_int64 | int64_t | +| oid | dt_int32 | int32_t | +| char, varchar, text, cstring, bpchar | dt_string | std::string | +| abstime, reltime, date, time, timestamp, timestamptz, timetz | dt_date | std::tm | (See the [dynamic resultset binding](../types.md#dynamic-binding) documentation for general information on using the `row` class.) diff --git a/docs/backends/sqlite3.md b/docs/backends/sqlite3.md index 4d449d057..a7df2ea44 100644 --- a/docs/backends/sqlite3.md +++ b/docs/backends/sqlite3.md @@ -75,14 +75,16 @@ When calling `row::get()`, the type you should pass as T depends upon the und For the SQLite3 backend, this type mapping is complicated by the fact the SQLite3 does not enforce [types][INTEGER_PRIMARY_KEY] and makes no attempt to validate the type names used in table creation or alteration statements. SQLite3 will return the type as a string, SOCI will recognize the following strings and match them the corresponding SOCI types: -|SQLite3 Data Type|SOCI Data Type|`row::get` specializations| -|--- |--- |--- | -|*float*, *double*|dt_double|double| -|*int8*, *bigint*|dt_long_long|long long| -|*unsigned big int*|dt_unsigned_long_long|unsigned long long| -|*int*, *boolean*|dt_integer|int| -|*text, *char*|dt_string|std::string| -|*date*, *time*|dt_date|std::tm| +| SQLite3 Data Type | SOCI Data Type | `row::get` specializations | +| ------------------------------------------------------------------------------------------------------------ | -------------- | ----------------------------- | +| *float*, *decimal*, *double*, *double precision*, *number*, *numeric*, *real* | dt_double | double | +| *tinyint* | dt_int8 | int8_t | +| *smallint* | dt_int16 | int16_t | +| *int*, *integer*, *int2*, *mediumint*, *boolean* | dt_int32 | int32_t | +| *int8*, *bigint* | dt_int64 | int64_t | +| *unsigned big int* | dt_uint64 | uint64_t | +| *text*, *char*, *character*, *clob*, *native character*, *nchar*, *nvarchar*, *varchar*, *varying character* | dt_string | std::string | +| *date*, *time*, *datetime* | dt_date | std::tm | [INTEGER_PRIMARY_KEY] : There is one case where SQLite3 enforces type. If a column is declared as "integer primary key", then SQLite3 uses that as an alias to the internal ROWID column that exists for every table. Only integers are allowed in this column. diff --git a/docs/interfaces.md b/docs/interfaces.md index 36480734d..d63206e81 100644 --- a/docs/interfaces.md +++ b/docs/interfaces.md @@ -56,8 +56,8 @@ session_handle sql = soci_create_session("postgresql://dbname=mydb"); statement_handle st = soci_create_statement(sql); -soci_use_int(st, "id"); -soci_set_use_int(st, "id", 123); +soci_use_int32(st, "id"); +soci_set_use_int32(st, "id", 123); int namePosition = soci_into_string(st); diff --git a/docs/types.md b/docs/types.md index 201fea440..f02278672 100644 --- a/docs/types.md +++ b/docs/types.md @@ -7,7 +7,7 @@ The static binding for types is most useful when the types used in the database The following types are currently supported for use with `into` and `use` expressions: * `char` (for character values) -* `short`, `int`, `unsigned long`, `long long`, `double` (for numeric values) +* `int8_t`, `uint8_t`, `int16_t`, `uint16_t`, `int32_t`, `uint32_t`, `int64_t`, `uint64_t`, `double` (for numeric values) * `std::string` (for string values) * `std::tm` (for datetime values) * `soci::statement` (for nested statements and PL/SQL cursors) @@ -16,15 +16,22 @@ The following types are currently supported for use with `into` and `use` expres See the test code that accompanies the library to see how each of these types is used. +Note that the fixed-size types `int32_t`, `int64_t` etc. are only typedefs for the fundamental types `int`, `long` etc. +This means that the two can be used interchangeably when interacting with SOCI and you can choose which one of them you want to use in your code. + ### Static binding for bulk operations Bulk inserts, updates, and selects are supported through the following `std::vector` based into and use types: * `std::vector` -* `std::vector` -* `std::vector` -* `std::vector` -* `std::vector` +* `std::vector` +* `std::vector` +* `std::vector` +* `std::vector` +* `std::vector` +* `std::vector` +* `std::vector` +* `std::vector` * `std::vector` * `std::vector` * `std::vector` @@ -65,14 +72,29 @@ for(std::size_t i = 0; i != r.size(); ++i) case dt_double: doc << r.get(i); break; - case dt_integer: - doc << r.get(i); + case dt_int8: + doc << r.get(i); + break; + case dt_uint8: + doc << r.get(i); + break; + case dt_int16: + doc << r.get(i); + break; + case dt_uint16: + doc << r.get(i); + break; + case dt_int32: + doc << r.get(i); + break; + case dt_uint32: + doc << r.get(i); break; - case dt_long_long: - doc << r.get(i); + case dt_int64: + doc << r.get(i); break; - case dt_unsigned_long_long: - doc << r.get(i); + case dt_uint64: + doc << r.get(i); break; case dt_date: std::tm when = r.get(i); @@ -92,9 +114,14 @@ The type `T` parameter that should be passed to `row::get()` depends on the S | SOCI Data Type | `row::get` specialization | |----------------|------------------------------| | `dt_double` | `double` | -| `dt_integer` | `int` | -| `dt_long_long` | `long long` | -| `dt_unsigned_long_long` | `unsigned long long`| +| `dt_int8` | `int8_t` | +| `dt_uint8` | `uint8_t` | +| `dt_int16` | `int16_t` | +| `dt_uint16` | `uint16_t` | +| `dt_int32` | `int32_t` | +| `dt_uint32` | `uint32_t` | +| `dt_int64` | `int64_t` | +| `dt_uint64` | `uint64_t` | | `dt_string` | `std::string` | | `dt_date` | `std::tm` | @@ -133,9 +160,14 @@ SOCI can be easily extended with support for user-defined datatypes. The extension mechanism relies on appropriate specialization of the `type_conversion` structure that converts to and from one of the following SOCI base types: * `double` -* `int` -* `long long` -* `unsigned long long` +* `int8_t` +* `uint8_t` +* `int16_t` +* `uint16_t` +* `int32_t` +* `uint32_t` +* `int64_t` +* `uint64_t` * `std::string` * `char` * `std::tm` diff --git a/docs/utilities.md b/docs/utilities.md index 110f0e19b..8410dd68d 100644 --- a/docs/utilities.md +++ b/docs/utilities.md @@ -9,7 +9,7 @@ SOCI supports some basic methods to construct portable DDL queries. That is, ins It is possible to create a new table in a single statement: ```cpp -sql.create_table("t1").column("i", soci::dt_integer).column("j", soci::dt_integer); +sql.create_table("t1").column("i", soci::dt_int32).column("j", soci::dt_int32); ``` Above, table "t1" will be created with two columns ("i", "j") of type integer. @@ -19,9 +19,9 @@ It is also possible to build similar statements piece by piece, which is useful ```cpp { soci::ddl_type ddl = sql.create_table("t2"); - ddl.column("i", soci::dt_integer); - ddl.column("j", soci::dt_integer); - ddl.column("k", soci::dt_integer)("not null"); + ddl.column("i", soci::dt_int32); + ddl.column("j", soci::dt_int32); + ddl.column("k", soci::dt_int32)("not null"); ddl.primary_key("t2_pk", "j"); } ``` @@ -31,9 +31,9 @@ The actual statement is executed at the end of above block, when the ddl object Columns can be added to and dropped from already existing tables as well: ```cpp -sql.add_column("t1", "k", soci::dt_integer); +sql.add_column("t1", "k", soci::dt_int32); // or with constraint: -//sql.add_column("t1", "k", soci::dt_integer)("not null"); +//sql.add_column("t1", "k", soci::dt_int32)("not null"); sql.drop_column("t1", "i"); ``` @@ -50,8 +50,8 @@ Tables with foreign keys to each other can be also created: ```cpp { soci::ddl_type ddl = sql.create_table("t3"); - ddl.column("x", soci::dt_integer); - ddl.column("y", soci::dt_integer); + ddl.column("x", soci::dt_int32); + ddl.column("y", soci::dt_int32); ddl.foreign_key("t3_fk", "x", "t2", "j"); } ``` From 8dba000f68ff10921f8b9e691218ee86b2127b18 Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Wed, 5 Oct 2022 23:23:52 +0200 Subject: [PATCH 20/46] Correct ODBC error message for unsigned types --- src/backends/odbc/statement.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/odbc/statement.cpp b/src/backends/odbc/statement.cpp index b7bf888da..2f7a775e7 100644 --- a/src/backends/odbc/statement.cpp +++ b/src/backends/odbc/statement.cpp @@ -359,7 +359,7 @@ void odbc_statement_backend::describe_column(int colNum, data_type & type, if (is_odbc_error(rc_colattr)) { std::ostringstream ss; - ss << "getting col attribute of column at position " << colNum; + ss << "getting \"unsigned\" col attribute of the column at position " << colNum; throw odbc_soci_error(SQL_HANDLE_STMT, hstmt_, ss.str()); } From 3d1617085c1bfb16ef5849288ab41ec6c9993032 Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Wed, 28 Sep 2022 19:47:40 +0200 Subject: [PATCH 21/46] Replace stdint.h with cstdint --- include/private/firebird/common.h | 2 +- include/private/soci-exchange-cast.h | 2 +- include/soci/column-info.h | 2 +- include/soci/exchange-traits.h | 2 +- include/soci/soci-simple.h | 2 +- include/soci/sqlite3/soci-sqlite3.h | 2 +- src/backends/db2/standard-into-type.cpp | 2 +- src/backends/db2/standard-use-type.cpp | 2 +- src/backends/db2/vector-into-type.cpp | 2 +- src/backends/db2/vector-use-type.cpp | 2 +- src/backends/mysql/standard-into-type.cpp | 2 +- src/backends/mysql/standard-use-type.cpp | 2 +- src/backends/mysql/vector-into-type.cpp | 2 +- src/backends/mysql/vector-use-type.cpp | 2 +- src/backends/odbc/standard-into-type.cpp | 2 +- src/backends/odbc/standard-use-type.cpp | 2 +- src/backends/odbc/vector-into-type.cpp | 2 +- src/backends/odbc/vector-use-type.cpp | 2 +- src/backends/oracle/standard-into-type.cpp | 2 +- src/backends/oracle/standard-use-type.cpp | 2 +- src/backends/oracle/vector-into-type.cpp | 2 +- src/backends/oracle/vector-use-type.cpp | 2 +- src/backends/postgresql/standard-into-type.cpp | 2 +- src/backends/postgresql/standard-use-type.cpp | 2 +- src/backends/postgresql/vector-into-type.cpp | 2 +- src/backends/postgresql/vector-use-type.cpp | 2 +- src/backends/sqlite3/statement.cpp | 2 +- src/backends/sqlite3/vector-into-type.cpp | 2 +- src/backends/sqlite3/vector-use-type.cpp | 2 +- src/core/statement.cpp | 2 +- tests/common-tests.h | 2 +- tests/mysql/test-mysql.cpp | 2 +- tests/sqlite3/test-sqlite3.cpp | 2 +- 33 files changed, 33 insertions(+), 33 deletions(-) diff --git a/include/private/firebird/common.h b/include/private/firebird/common.h index 6e07ce45e..0e6b89d4b 100644 --- a/include/private/firebird/common.h +++ b/include/private/firebird/common.h @@ -10,13 +10,13 @@ #include "soci/firebird/soci-firebird.h" #include "soci-compiler.h" +#include #include #include #include #include #include #include -#include #include #include #include diff --git a/include/private/soci-exchange-cast.h b/include/private/soci-exchange-cast.h index 147a395f9..596386dc4 100644 --- a/include/private/soci-exchange-cast.h +++ b/include/private/soci-exchange-cast.h @@ -11,8 +11,8 @@ #include "soci/soci-backend.h" #include "soci/type-wrappers.h" +#include #include -#include namespace soci { diff --git a/include/soci/column-info.h b/include/soci/column-info.h index bc7f683a9..5cc7ed22c 100644 --- a/include/soci/column-info.h +++ b/include/soci/column-info.h @@ -12,7 +12,7 @@ #include "soci/type-conversion.h" #include "soci/values.h" -#include +#include namespace soci { diff --git a/include/soci/exchange-traits.h b/include/soci/exchange-traits.h index 971ba5a8b..d70de2e26 100644 --- a/include/soci/exchange-traits.h +++ b/include/soci/exchange-traits.h @@ -12,8 +12,8 @@ #include "soci/soci-backend.h" #include "soci/type-wrappers.h" // std +#include #include -#include #include #include diff --git a/include/soci/soci-simple.h b/include/soci/soci-simple.h index 203adbe90..01a32f760 100644 --- a/include/soci/soci-simple.h +++ b/include/soci/soci-simple.h @@ -10,7 +10,7 @@ #include "soci/soci-platform.h" -#include +#include #ifdef __cplusplus extern "C" diff --git a/include/soci/sqlite3/soci-sqlite3.h b/include/soci/sqlite3/soci-sqlite3.h index 3d2a62794..f62282cce 100644 --- a/include/soci/sqlite3/soci-sqlite3.h +++ b/include/soci/sqlite3/soci-sqlite3.h @@ -17,7 +17,7 @@ #endif #include -#include +#include #include #include diff --git a/src/backends/db2/standard-into-type.cpp b/src/backends/db2/standard-into-type.cpp index 9558619ca..f476d1a55 100644 --- a/src/backends/db2/standard-into-type.cpp +++ b/src/backends/db2/standard-into-type.cpp @@ -11,8 +11,8 @@ #include "soci-exchange-cast.h" #include "soci-mktime.h" #include "common.h" +#include #include -#include using namespace soci; using namespace soci::details; diff --git a/src/backends/db2/standard-use-type.cpp b/src/backends/db2/standard-use-type.cpp index 44e1e70cd..c6f08c8a0 100644 --- a/src/backends/db2/standard-use-type.cpp +++ b/src/backends/db2/standard-use-type.cpp @@ -10,11 +10,11 @@ #include "soci/db2/soci-db2.h" #include "soci-exchange-cast.h" #include +#include #include #include #include #include -#include using namespace soci; using namespace soci::details; diff --git a/src/backends/db2/vector-into-type.cpp b/src/backends/db2/vector-into-type.cpp index 8c6dc9bf6..664065d95 100644 --- a/src/backends/db2/vector-into-type.cpp +++ b/src/backends/db2/vector-into-type.cpp @@ -10,11 +10,11 @@ #include "soci/db2/soci-db2.h" #include "soci-mktime.h" #include +#include #include #include #include #include -#include using namespace soci; using namespace soci::details; diff --git a/src/backends/db2/vector-use-type.cpp b/src/backends/db2/vector-use-type.cpp index b75baf15d..972002ea2 100644 --- a/src/backends/db2/vector-use-type.cpp +++ b/src/backends/db2/vector-use-type.cpp @@ -10,11 +10,11 @@ #include "soci/soci-platform.h" #include "soci/db2/soci-db2.h" #include +#include #include #include #include #include -#include #ifdef _MSC_VER // disables the warning about converting int to void*. This is a 64 bit compatibility diff --git a/src/backends/mysql/standard-into-type.cpp b/src/backends/mysql/standard-into-type.cpp index 15528bc1f..06f98e694 100644 --- a/src/backends/mysql/standard-into-type.cpp +++ b/src/backends/mysql/standard-into-type.cpp @@ -14,10 +14,10 @@ #include "soci-mktime.h" // std #include +#include #include #include #include -#include #include #ifdef _MSC_VER diff --git a/src/backends/mysql/standard-use-type.cpp b/src/backends/mysql/standard-use-type.cpp index e88633e67..9f8cd35d8 100644 --- a/src/backends/mysql/standard-use-type.cpp +++ b/src/backends/mysql/standard-use-type.cpp @@ -14,10 +14,10 @@ #include "soci-exchange-cast.h" // std #include +#include #include #include #include -#include using namespace soci; using namespace soci::details; diff --git a/src/backends/mysql/vector-into-type.cpp b/src/backends/mysql/vector-into-type.cpp index f9de6b654..908888fed 100644 --- a/src/backends/mysql/vector-into-type.cpp +++ b/src/backends/mysql/vector-into-type.cpp @@ -12,8 +12,8 @@ #include "common.h" #include "soci/soci-platform.h" #include +#include #include -#include using namespace soci; using namespace soci::details; diff --git a/src/backends/mysql/vector-use-type.cpp b/src/backends/mysql/vector-use-type.cpp index 25a283001..144f23348 100644 --- a/src/backends/mysql/vector-use-type.cpp +++ b/src/backends/mysql/vector-use-type.cpp @@ -14,12 +14,12 @@ // std #include #include +#include #include #include #include #include #include -#include #include #include diff --git a/src/backends/odbc/standard-into-type.cpp b/src/backends/odbc/standard-into-type.cpp index d856549b3..37c028a3f 100644 --- a/src/backends/odbc/standard-into-type.cpp +++ b/src/backends/odbc/standard-into-type.cpp @@ -12,8 +12,8 @@ #include "soci-cstrtoi.h" #include "soci-exchange-cast.h" #include "soci-mktime.h" +#include #include -#include using namespace soci; using namespace soci::details; diff --git a/src/backends/odbc/standard-use-type.cpp b/src/backends/odbc/standard-use-type.cpp index 204b66944..fc7662e02 100644 --- a/src/backends/odbc/standard-use-type.cpp +++ b/src/backends/odbc/standard-use-type.cpp @@ -9,11 +9,11 @@ #include "soci-compiler.h" #include "soci-exchange-cast.h" #include +#include #include #include #include #include -#include using namespace soci; using namespace soci::details; diff --git a/src/backends/odbc/vector-into-type.cpp b/src/backends/odbc/vector-into-type.cpp index 28d379c3c..3e864d9be 100644 --- a/src/backends/odbc/vector-into-type.cpp +++ b/src/backends/odbc/vector-into-type.cpp @@ -15,11 +15,11 @@ #include "soci-vector-helpers.h" #include #include +#include #include #include #include #include -#include using namespace soci; using namespace soci::details; diff --git a/src/backends/odbc/vector-use-type.cpp b/src/backends/odbc/vector-use-type.cpp index 45b845f6e..dad2233c8 100644 --- a/src/backends/odbc/vector-use-type.cpp +++ b/src/backends/odbc/vector-use-type.cpp @@ -11,11 +11,11 @@ #include "soci-compiler.h" #include "soci-vector-helpers.h" #include +#include #include #include #include #include -#include #ifdef _MSC_VER // disables the warning about converting int to void*. This is a 64 bit compatibility diff --git a/src/backends/oracle/standard-into-type.cpp b/src/backends/oracle/standard-into-type.cpp index 3983d795c..01292313b 100644 --- a/src/backends/oracle/standard-into-type.cpp +++ b/src/backends/oracle/standard-into-type.cpp @@ -16,12 +16,12 @@ #include "soci-exchange-cast.h" #include "soci-mktime.h" #include +#include #include #include #include #include #include -#include #ifdef _MSC_VER #pragma warning(disable:4355) diff --git a/src/backends/oracle/standard-use-type.cpp b/src/backends/oracle/standard-use-type.cpp index 3b3b51c33..0aac00e10 100644 --- a/src/backends/oracle/standard-use-type.cpp +++ b/src/backends/oracle/standard-use-type.cpp @@ -20,12 +20,12 @@ #include "soci-mktime.h" #include +#include #include #include #include #include #include -#include #ifdef _MSC_VER #pragma warning(disable:4355) diff --git a/src/backends/oracle/vector-into-type.cpp b/src/backends/oracle/vector-into-type.cpp index baa295e0e..d838b6849 100644 --- a/src/backends/oracle/vector-into-type.cpp +++ b/src/backends/oracle/vector-into-type.cpp @@ -14,12 +14,12 @@ #include "soci-mktime.h" #include "soci-vector-helpers.h" #include +#include #include #include #include #include #include -#include #ifdef _MSC_VER #pragma warning(disable:4355) diff --git a/src/backends/oracle/vector-use-type.cpp b/src/backends/oracle/vector-use-type.cpp index 069449a9f..11fda2e11 100644 --- a/src/backends/oracle/vector-use-type.cpp +++ b/src/backends/oracle/vector-use-type.cpp @@ -12,11 +12,11 @@ #include "soci/soci-platform.h" #include "soci-vector-helpers.h" #include +#include #include #include #include #include -#include #ifdef _MSC_VER #pragma warning(disable:4355) diff --git a/src/backends/postgresql/standard-into-type.cpp b/src/backends/postgresql/standard-into-type.cpp index 7bd50467c..023b1dda1 100644 --- a/src/backends/postgresql/standard-into-type.cpp +++ b/src/backends/postgresql/standard-into-type.cpp @@ -17,12 +17,12 @@ #include "soci-exchange-cast.h" #include // libpq #include +#include #include #include #include #include #include -#include using namespace soci; using namespace soci::details; diff --git a/src/backends/postgresql/standard-use-type.cpp b/src/backends/postgresql/standard-use-type.cpp index ff71996fa..9b454b551 100644 --- a/src/backends/postgresql/standard-use-type.cpp +++ b/src/backends/postgresql/standard-use-type.cpp @@ -15,12 +15,12 @@ #include "soci-exchange-cast.h" #include // libpq #include +#include #include #include #include #include #include -#include using namespace soci; using namespace soci::details; diff --git a/src/backends/postgresql/vector-into-type.cpp b/src/backends/postgresql/vector-into-type.cpp index d852dac39..fcdbadb19 100644 --- a/src/backends/postgresql/vector-into-type.cpp +++ b/src/backends/postgresql/vector-into-type.cpp @@ -14,11 +14,11 @@ #include "soci/type-wrappers.h" #include // libpq #include +#include #include #include #include #include -#include using namespace soci; using namespace soci::details; diff --git a/src/backends/postgresql/vector-use-type.cpp b/src/backends/postgresql/vector-use-type.cpp index 1487b191a..a0aa34965 100644 --- a/src/backends/postgresql/vector-use-type.cpp +++ b/src/backends/postgresql/vector-use-type.cpp @@ -13,12 +13,12 @@ #include "soci/type-wrappers.h" #include // libpq #include +#include #include #include #include #include #include -#include using namespace soci; using namespace soci::details; diff --git a/src/backends/sqlite3/statement.cpp b/src/backends/sqlite3/statement.cpp index fa5fc7439..19c4fc437 100644 --- a/src/backends/sqlite3/statement.cpp +++ b/src/backends/sqlite3/statement.cpp @@ -10,10 +10,10 @@ // std #include #include +#include #include #include #include -#include #include #ifdef _MSC_VER diff --git a/src/backends/sqlite3/vector-into-type.cpp b/src/backends/sqlite3/vector-into-type.cpp index e38659a84..14fd587c0 100644 --- a/src/backends/sqlite3/vector-into-type.cpp +++ b/src/backends/sqlite3/vector-into-type.cpp @@ -22,9 +22,9 @@ #include "common.h" // std #include +#include #include #include -#include #include #include #include diff --git a/src/backends/sqlite3/vector-use-type.cpp b/src/backends/sqlite3/vector-use-type.cpp index 9962d7bf1..b07a9afc5 100644 --- a/src/backends/sqlite3/vector-use-type.cpp +++ b/src/backends/sqlite3/vector-use-type.cpp @@ -13,10 +13,10 @@ #include "common.h" // std #include +#include #include #include #include -#include #include diff --git a/src/core/statement.cpp b/src/core/statement.cpp index 8f3d0a953..28b1f55e7 100644 --- a/src/core/statement.cpp +++ b/src/core/statement.cpp @@ -14,7 +14,7 @@ #include "soci-compiler.h" #include #include -#include +#include using namespace soci; using namespace soci::details; diff --git a/tests/common-tests.h b/tests/common-tests.h index 1e861ef58..6867ff05c 100644 --- a/tests/common-tests.h +++ b/tests/common-tests.h @@ -39,12 +39,12 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include #include diff --git a/tests/mysql/test-mysql.cpp b/tests/mysql/test-mysql.cpp index c6f39dcef..0d9159ee5 100644 --- a/tests/mysql/test-mysql.cpp +++ b/tests/mysql/test-mysql.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include std::string connectString; backend_factory const &backEnd = *soci::factory_mysql(); diff --git a/tests/sqlite3/test-sqlite3.cpp b/tests/sqlite3/test-sqlite3.cpp index 755959948..8636a96f7 100644 --- a/tests/sqlite3/test-sqlite3.cpp +++ b/tests/sqlite3/test-sqlite3.cpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include using namespace soci; using namespace soci::tests; From ff90687f2f613b2bea086e216b8d86471ce7b0a7 Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Wed, 5 Oct 2022 21:56:04 +0200 Subject: [PATCH 22/46] Add back removed dt_* and x_* types Types that refered to non-fixed-size types have been replaced in favor of their fixed-size types (e.g. dt_integer -> dt_int32, x_short -> x_int16). To be backwards compatible, we need to keep all of the previous types though. --- docs/api/backend.md | 7 ++ docs/types.md | 29 +++--- docs/utilities.md | 16 ++-- include/soci/fixed-size-ints.h | 156 +++++++++++++++++++++++++++++++++ include/soci/soci-backend.h | 7 ++ include/soci/soci.h | 1 + 6 files changed, 195 insertions(+), 21 deletions(-) create mode 100644 include/soci/fixed-size-ints.h diff --git a/docs/api/backend.md b/docs/api/backend.md index 3041ba3cd..aa1066164 100644 --- a/docs/api/backend.md +++ b/docs/api/backend.md @@ -27,9 +27,12 @@ enum data_type dt_int16, dt_uint16, dt_int32, + dt_integer = dt_int32, dt_uint32, dt_int64, + dt_long_long = dt_int64, dt_uint64, + dt_unsigned_long_long = dt_uint64, dt_double, dt_date, dt_blob, @@ -47,11 +50,15 @@ enum exchange_type x_int8, x_uint8, x_int16, + x_short = x_int16, x_uint16, x_int32, + x_integer = x_int32, x_uint32, x_int64, + x_long_long = x_int64, x_uint64, + x_unsigned_long_long = x_uint64, x_double, x_stdtm, x_statement, diff --git a/docs/types.md b/docs/types.md index f02278672..e571049d5 100644 --- a/docs/types.md +++ b/docs/types.md @@ -111,19 +111,22 @@ The type `T` parameter that should be passed to `row::get()` depends on the S `row::get()` throws an exception of type `std::bad_cast` if an incorrect type `T` is requested. -| SOCI Data Type | `row::get` specialization | -|----------------|------------------------------| -| `dt_double` | `double` | -| `dt_int8` | `int8_t` | -| `dt_uint8` | `uint8_t` | -| `dt_int16` | `int16_t` | -| `dt_uint16` | `uint16_t` | -| `dt_int32` | `int32_t` | -| `dt_uint32` | `uint32_t` | -| `dt_int64` | `int64_t` | -| `dt_uint64` | `uint64_t` | -| `dt_string` | `std::string` | -| `dt_date` | `std::tm` | +| SOCI Data Type | `row::get` specialization | +|-------------------------|------------------------------| +| `dt_double` | `double` | +| `dt_int8` | `int8_t` | +| `dt_uint8` | `uint8_t` | +| `dt_int16` | `int16_t` | +| `dt_uint16` | `uint16_t` | +| `dt_int32` | `int32_t` | +| `dt_integer` | `int32_t` | +| `dt_uint32` | `uint32_t` | +| `dt_int64` | `int64_t` | +| `dt_long_long` | `int64_t` | +| `dt_uint64` | `uint64_t` | +| `dt_unsigned_long_long` | `uint64_t` | +| `dt_string` | `std::string` | +| `dt_date` | `std::tm` | The mapping of underlying database column types to SOCI datatypes is database specific. See the [backend documentation](backends/index.md) for details. diff --git a/docs/utilities.md b/docs/utilities.md index 8410dd68d..110f0e19b 100644 --- a/docs/utilities.md +++ b/docs/utilities.md @@ -9,7 +9,7 @@ SOCI supports some basic methods to construct portable DDL queries. That is, ins It is possible to create a new table in a single statement: ```cpp -sql.create_table("t1").column("i", soci::dt_int32).column("j", soci::dt_int32); +sql.create_table("t1").column("i", soci::dt_integer).column("j", soci::dt_integer); ``` Above, table "t1" will be created with two columns ("i", "j") of type integer. @@ -19,9 +19,9 @@ It is also possible to build similar statements piece by piece, which is useful ```cpp { soci::ddl_type ddl = sql.create_table("t2"); - ddl.column("i", soci::dt_int32); - ddl.column("j", soci::dt_int32); - ddl.column("k", soci::dt_int32)("not null"); + ddl.column("i", soci::dt_integer); + ddl.column("j", soci::dt_integer); + ddl.column("k", soci::dt_integer)("not null"); ddl.primary_key("t2_pk", "j"); } ``` @@ -31,9 +31,9 @@ The actual statement is executed at the end of above block, when the ddl object Columns can be added to and dropped from already existing tables as well: ```cpp -sql.add_column("t1", "k", soci::dt_int32); +sql.add_column("t1", "k", soci::dt_integer); // or with constraint: -//sql.add_column("t1", "k", soci::dt_int32)("not null"); +//sql.add_column("t1", "k", soci::dt_integer)("not null"); sql.drop_column("t1", "i"); ``` @@ -50,8 +50,8 @@ Tables with foreign keys to each other can be also created: ```cpp { soci::ddl_type ddl = sql.create_table("t3"); - ddl.column("x", soci::dt_int32); - ddl.column("y", soci::dt_int32); + ddl.column("x", soci::dt_integer); + ddl.column("y", soci::dt_integer); ddl.foreign_key("t3_fk", "x", "t2", "j"); } ``` diff --git a/include/soci/fixed-size-ints.h b/include/soci/fixed-size-ints.h new file mode 100644 index 000000000..59aab9f81 --- /dev/null +++ b/include/soci/fixed-size-ints.h @@ -0,0 +1,156 @@ +#ifndef SOCI_FIXED_SIZE_INTS_H_INCLUDED +#define SOCI_FIXED_SIZE_INTS_H_INCLUDED + +#include "soci/type-conversion-traits.h" + +#include + +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(_WIN64) +template <> +struct type_conversion +{ + 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(in); + } + + static void to_base(long const & in, base_type & out, indicator & ind) + { + out = static_cast(in); + ind = i_ok; + } +}; + +template <> +struct type_conversion +{ + 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(in); + } + + static void to_base(unsigned long const & in, base_type & out, indicator & ind) + { + out = static_cast(in); + ind = i_ok; + } +}; +#elif defined(__APPLE__) +template <> +struct type_conversion +{ + 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(in); + } + + static void to_base(long const & in, base_type & out, indicator & ind) + { + out = static_cast(in); + ind = i_ok; + } +}; + +template <> +struct type_conversion +{ + 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(in); + } + + static void to_base(unsigned long const & in, base_type & out, indicator & ind) + { + out = static_cast(in); + ind = i_ok; + } +}; +#elif defined(__LP64__) || (__WORDSIZE == 64) +template <> +struct type_conversion +{ + 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(in); + } + + static void to_base(long long const & in, base_type & out, indicator & ind) + { + out = static_cast(in); + ind = i_ok; + } +}; + +template <> +struct type_conversion +{ + 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(in); + } + + static void to_base(unsigned long long const & in, base_type & out, indicator & ind) + { + out = static_cast(in); + ind = i_ok; + } +}; +#else +#error "Unhandled type architecture" +#endif + +} // namespace soci + +#endif // SOCI_FIXED_SIZE_INTS_H_INCLUDED diff --git a/include/soci/soci-backend.h b/include/soci/soci-backend.h index ccd0b7a8a..5d3d94b0f 100644 --- a/include/soci/soci-backend.h +++ b/include/soci/soci-backend.h @@ -28,9 +28,12 @@ enum data_type dt_int16, dt_uint16, dt_int32, + dt_integer = dt_int32, dt_uint32, dt_int64, + dt_long_long = dt_int64, dt_uint64, + dt_unsigned_long_long = dt_uint64, dt_double, dt_date, dt_blob, @@ -54,11 +57,15 @@ enum exchange_type x_int8, x_uint8, x_int16, + x_short = x_int16, x_uint16, x_int32, + x_integer = x_int32, x_uint32, x_int64, + x_long_long = x_int64, x_uint64, + x_unsigned_long_long = x_uint64, x_double, x_stdtm, x_statement, diff --git a/include/soci/soci.h b/include/soci/soci.h index 291878366..1968d0866 100644 --- a/include/soci/soci.h +++ b/include/soci/soci.h @@ -15,6 +15,7 @@ #include "soci/blob-exchange.h" #include "soci/column-info.h" #include "soci/connection-pool.h" +#include "soci/fixed-size-ints.h" #include "soci/error.h" #include "soci/exchange-traits.h" #include "soci/into.h" From 367c0c0341884f8434ccb611d43fd15471737699 Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Wed, 5 Oct 2022 23:11:23 +0200 Subject: [PATCH 23/46] Revert unnecessary changes in unit tests --- tests/common-tests.h | 36 ++++++++++++++-------------- tests/firebird/test-firebird.cpp | 4 ++-- tests/mysql/test-mysql.cpp | 10 ++++---- tests/oracle/test-oracle.cpp | 32 ++++++++++++------------- tests/postgresql/test-postgresql.cpp | 32 ++++++++++++------------- tests/sqlite3/test-sqlite3.cpp | 8 +++---- 6 files changed, 61 insertions(+), 61 deletions(-) diff --git a/tests/common-tests.h b/tests/common-tests.h index 6867ff05c..033148f35 100644 --- a/tests/common-tests.h +++ b/tests/common-tests.h @@ -3014,7 +3014,7 @@ TEST_CASE_METHOD(common_tests, "Dynamic row binding", "[core][dynamic]") CHECK(r.size() == 5); CHECK(r.get_properties(0).get_data_type() == dt_double); - CHECK(r.get_properties(1).get_data_type() == dt_int32); + CHECK(r.get_properties(1).get_data_type() == dt_integer); CHECK(r.get_properties(2).get_data_type() == dt_string); CHECK(r.get_properties(3).get_data_type() == dt_date); @@ -3022,7 +3022,7 @@ TEST_CASE_METHOD(common_tests, "Dynamic row binding", "[core][dynamic]") // - to comply with the implementation for Oracle CHECK(r.get_properties(4).get_data_type() == dt_string); - CHECK(r.get_properties("NUM_INT").get_data_type() == dt_int32); + CHECK(r.get_properties("NUM_INT").get_data_type() == dt_integer); CHECK(r.get_properties(0).get_name() == "NUM_FLOAT"); CHECK(r.get_properties(1).get_name() == "NUM_INT"); @@ -3088,7 +3088,7 @@ TEST_CASE_METHOD(common_tests, "Dynamic row binding", "[core][dynamic]") CHECK(r.size() == 5); CHECK(r.get_properties(0).get_data_type() == dt_double); - CHECK(r.get_properties(1).get_data_type() == dt_int32); + CHECK(r.get_properties(1).get_data_type() == dt_integer); CHECK(r.get_properties(2).get_data_type() == dt_string); CHECK(r.get_properties(3).get_data_type() == dt_date); @@ -3097,7 +3097,7 @@ TEST_CASE_METHOD(common_tests, "Dynamic row binding", "[core][dynamic]") CHECK(r.size() == 2); CHECK(r.get_properties(0).get_data_type() == dt_string); - CHECK(r.get_properties(1).get_data_type() == dt_int32); + CHECK(r.get_properties(1).get_data_type() == dt_integer); // Check if row object is movable row moved = std::move(r); @@ -3107,7 +3107,7 @@ TEST_CASE_METHOD(common_tests, "Dynamic row binding", "[core][dynamic]") CHECK(r.size() == 0); CHECK(moved.get_properties(0).get_data_type() == dt_string); - CHECK(moved.get_properties(1).get_data_type() == dt_int32); + CHECK(moved.get_properties(1).get_data_type() == dt_integer); } } @@ -3128,7 +3128,7 @@ TEST_CASE_METHOD(common_tests, "Dynamic row binding 2", "[core][dynamic]") sql << "select val from soci_test where id = :id", use(id), into(r); CHECK(r.size() == 1); - CHECK(r.get_properties(0).get_data_type() == dt_int32); + CHECK(r.get_properties(0).get_data_type() == dt_integer); CHECK(r.get(0) == 20); } { @@ -3140,19 +3140,19 @@ TEST_CASE_METHOD(common_tests, "Dynamic row binding 2", "[core][dynamic]") id = 2; st.execute(true); CHECK(r.size() == 1); - CHECK(r.get_properties(0).get_data_type() == dt_int32); + CHECK(r.get_properties(0).get_data_type() == dt_integer); CHECK(r.get(0) == 20); id = 3; st.execute(true); CHECK(r.size() == 1); - CHECK(r.get_properties(0).get_data_type() == dt_int32); + CHECK(r.get_properties(0).get_data_type() == dt_integer); CHECK(r.get(0) == 30); id = 1; st.execute(true); CHECK(r.size() == 1); - CHECK(r.get_properties(0).get_data_type() == dt_int32); + CHECK(r.get_properties(0).get_data_type() == dt_integer); CHECK(r.get(0) == 10); } } @@ -3577,11 +3577,11 @@ TEST_CASE_METHOD(common_tests, "Reading rows from rowset", "[core][row][rowset]" // Properties CHECK(r1.size() == 5); CHECK(r1.get_properties(0).get_data_type() == dt_double); - CHECK(r1.get_properties(1).get_data_type() == dt_int32); + CHECK(r1.get_properties(1).get_data_type() == dt_integer); CHECK(r1.get_properties(2).get_data_type() == dt_string); CHECK(r1.get_properties(3).get_data_type() == dt_date); CHECK(r1.get_properties(4).get_data_type() == dt_string); - CHECK(r1.get_properties("NUM_INT").get_data_type() == dt_int32); + CHECK(r1.get_properties("NUM_INT").get_data_type() == dt_integer); // Data @@ -3640,11 +3640,11 @@ TEST_CASE_METHOD(common_tests, "Reading rows from rowset", "[core][row][rowset]" // Properties CHECK(r2.size() == 5); CHECK(r2.get_properties(0).get_data_type() == dt_double); - CHECK(r2.get_properties(1).get_data_type() == dt_int32); + CHECK(r2.get_properties(1).get_data_type() == dt_integer); CHECK(r2.get_properties(2).get_data_type() == dt_string); CHECK(r2.get_properties(3).get_data_type() == dt_date); CHECK(r2.get_properties(4).get_data_type() == dt_string); - CHECK(r2.get_properties("NUM_INT").get_data_type() == dt_int32); + CHECK(r2.get_properties("NUM_INT").get_data_type() == dt_integer); std::string newName = r2.get(2); CHECK(name != newName); @@ -3702,7 +3702,7 @@ TEST_CASE_METHOD(common_tests, "Reading rows from rowset", "[core][row][rowset]" // Properties CHECK(r1.size() == 5); - CHECK(r1.get_properties(0).get_data_type() == dt_int32); + CHECK(r1.get_properties(0).get_data_type() == dt_integer); CHECK(r1.get_properties(1).get_data_type() == dt_double); CHECK(r1.get_properties(2).get_data_type() == dt_string); CHECK(r1.get_properties(3).get_data_type() == dt_date); @@ -4051,8 +4051,8 @@ TEST_CASE_METHOD(common_tests, "NULL with optional", "[core][boost][null]") // for the id column - that's why the code below skips this column // and tests the remaining column only. - //CHECK(r1.get_properties(0).get_data_type() == dt_int32); - CHECK(r1.get_properties(1).get_data_type() == dt_int32); + //CHECK(r1.get_properties(0).get_data_type() == dt_integer); + CHECK(r1.get_properties(1).get_data_type() == dt_integer); CHECK(r1.get_properties(2).get_data_type() == dt_string); //CHECK(r1.get(0) == 1); CHECK(r1.get(1) == 5); @@ -4068,8 +4068,8 @@ TEST_CASE_METHOD(common_tests, "NULL with optional", "[core][boost][null]") CHECK(r2.size() == 3); - // CHECK(r2.get_properties(0).get_data_type() == dt_int32); - CHECK(r2.get_properties(1).get_data_type() == dt_int32); + // CHECK(r2.get_properties(0).get_data_type() == dt_integer); + CHECK(r2.get_properties(1).get_data_type() == dt_integer); CHECK(r2.get_properties(2).get_data_type() == dt_string); //CHECK(r2.get(0) == 2); try diff --git a/tests/firebird/test-firebird.cpp b/tests/firebird/test-firebird.cpp index fa69a2ab6..49f59185d 100644 --- a/tests/firebird/test-firebird.cpp +++ b/tests/firebird/test-firebird.cpp @@ -772,7 +772,7 @@ TEST_CASE("Firebird dynamic binding", "[firebird][dynamic]") CHECK(r.get_properties(1).get_name() == "MSG"); CHECK(r.get_properties(2).get_name() == "NTEST"); - CHECK(r.get_properties(0).get_data_type() == dt_int32); + CHECK(r.get_properties(0).get_data_type() == dt_integer); CHECK(r.get_properties(1).get_data_type() == dt_string); CHECK(r.get_properties(2).get_data_type() == dt_double); @@ -781,7 +781,7 @@ TEST_CASE("Firebird dynamic binding", "[firebird][dynamic]") CHECK(r.get_properties("MSG").get_name() == "MSG"); CHECK(r.get_properties("NTEST").get_name() == "NTEST"); - CHECK(r.get_properties("ID").get_data_type() == dt_int32); + CHECK(r.get_properties("ID").get_data_type() == dt_integer); CHECK(r.get_properties("MSG").get_data_type() == dt_string); CHECK(r.get_properties("NTEST").get_data_type() == dt_double); diff --git a/tests/mysql/test-mysql.cpp b/tests/mysql/test-mysql.cpp index 0d9159ee5..aed9952fb 100644 --- a/tests/mysql/test-mysql.cpp +++ b/tests/mysql/test-mysql.cpp @@ -689,7 +689,7 @@ TEST_CASE("MySQL tinyint", "[mysql][int][tinyint]") sql << "select val from soci_test", into(r); REQUIRE(r.size() == 1); CHECK(r.get_properties("val").get_data_type() == dt_uint32); - CHECK(r.get("val") == 0xffffff00); + CHECK(r.get("val") == 0xffffff00); } { soci::session sql(backEnd, connectString); @@ -718,8 +718,8 @@ TEST_CASE("MySQL tinyint", "[mysql][int][tinyint]") row r; sql << "select val from soci_test", into(r); REQUIRE(r.size() == 1); - CHECK(r.get_properties("val").get_data_type() == dt_uint64); - CHECK(r.get("val") == 123456789012345ULL); + CHECK(r.get_properties("val").get_data_type() == dt_unsigned_long_long); + CHECK(r.get("val") == 123456789012345ULL); } { soci::session sql(backEnd, connectString); @@ -728,8 +728,8 @@ TEST_CASE("MySQL tinyint", "[mysql][int][tinyint]") row r; sql << "select val from soci_test", into(r); REQUIRE(r.size() == 1); - CHECK(r.get_properties("val").get_data_type() == dt_int64); - CHECK(r.get("val") == -123456789012345LL); + CHECK(r.get_properties("val").get_data_type() == dt_long_long); + CHECK(r.get("val") == -123456789012345LL); } } diff --git a/tests/oracle/test-oracle.cpp b/tests/oracle/test-oracle.cpp index 75b170b67..ca6918188 100644 --- a/tests/oracle/test-oracle.cpp +++ b/tests/oracle/test-oracle.cpp @@ -1089,7 +1089,7 @@ TEST_CASE("Oracle DDL with metadata", "[oracle][ddl]") std::string ddl_t3 = "DDL_T3"; // single-expression variant: - sql.create_table(ddl_t1).column("I", soci::dt_int32).column("J", soci::dt_int32); + sql.create_table(ddl_t1).column("I", soci::dt_integer).column("J", soci::dt_integer); // check whether this table was created: @@ -1122,13 +1122,13 @@ TEST_CASE("Oracle DDL with metadata", "[oracle][ddl]") { if (ci.name == "I") { - CHECK(ci.type == soci::dt_int32); + CHECK(ci.type == soci::dt_integer); CHECK(ci.nullable); i_found = true; } else if (ci.name == "J") { - CHECK(ci.type == soci::dt_int32); + CHECK(ci.type == soci::dt_integer); CHECK(ci.nullable); j_found = true; } @@ -1148,24 +1148,24 @@ TEST_CASE("Oracle DDL with metadata", "[oracle][ddl]") // (note: statement is executed when ddl object goes out of scope) { soci::ddl_type ddl = sql.create_table(ddl_t2); - ddl.column("I", soci::dt_int32); - ddl.column("J", soci::dt_int32); - ddl.column("K", soci::dt_int32)("not null"); + ddl.column("I", soci::dt_integer); + ddl.column("J", soci::dt_integer); + ddl.column("K", soci::dt_integer)("not null"); ddl.primary_key("t2_pk", "J"); } - sql.add_column(ddl_t1, "K", soci::dt_int32); + sql.add_column(ddl_t1, "K", soci::dt_integer); sql.add_column(ddl_t1, "BIG", soci::dt_string, 0); // "unlimited" length -> CLOB sql.drop_column(ddl_t1, "I"); // or with constraint as in t2: - sql.add_column(ddl_t2, "M", soci::dt_int32)("not null"); + sql.add_column(ddl_t2, "M", soci::dt_integer)("not null"); // third table with a foreign key to the second one { soci::ddl_type ddl = sql.create_table(ddl_t3); - ddl.column("X", soci::dt_int32); - ddl.column("Y", soci::dt_int32); + ddl.column("X", soci::dt_integer); + ddl.column("Y", soci::dt_integer); ddl.foreign_key("t3_fk", "X", ddl_t2, "J"); } @@ -1200,13 +1200,13 @@ TEST_CASE("Oracle DDL with metadata", "[oracle][ddl]") { if (ci.name == "J") { - CHECK(ci.type == soci::dt_int32); + CHECK(ci.type == soci::dt_integer); CHECK(ci.nullable); j_found = true; } else if (ci.name == "K") { - CHECK(ci.type == soci::dt_int32); + CHECK(ci.type == soci::dt_integer); CHECK(ci.nullable); k_found = true; } @@ -1241,25 +1241,25 @@ TEST_CASE("Oracle DDL with metadata", "[oracle][ddl]") { if (ci.name == "I") { - CHECK(ci.type == soci::dt_int32); + CHECK(ci.type == soci::dt_integer); CHECK(ci.nullable); i_found = true; } else if (ci.name == "J") { - CHECK(ci.type == soci::dt_int32); + CHECK(ci.type == soci::dt_integer); CHECK(ci.nullable == false); // primary key j_found = true; } else if (ci.name == "K") { - CHECK(ci.type == soci::dt_int32); + CHECK(ci.type == soci::dt_integer); CHECK(ci.nullable == false); k_found = true; } else if (ci.name == "M") { - CHECK(ci.type == soci::dt_int32); + CHECK(ci.type == soci::dt_integer); CHECK(ci.nullable == false); m_found = true; } diff --git a/tests/postgresql/test-postgresql.cpp b/tests/postgresql/test-postgresql.cpp index aed6fbce5..5a583f864 100644 --- a/tests/postgresql/test-postgresql.cpp +++ b/tests/postgresql/test-postgresql.cpp @@ -747,7 +747,7 @@ TEST_CASE("PostgreSQL DDL with metadata", "[postgresql][ddl]") std::string ddl_t3 = "ddl_t3"; // single-expression variant: - sql.create_table(ddl_t1).column("i", soci::dt_int32).column("j", soci::dt_int32); + sql.create_table(ddl_t1).column("i", soci::dt_integer).column("j", soci::dt_integer); // check whether this table was created: @@ -780,13 +780,13 @@ TEST_CASE("PostgreSQL DDL with metadata", "[postgresql][ddl]") { if (ci.name == "i") { - CHECK(ci.type == soci::dt_int32); + CHECK(ci.type == soci::dt_integer); CHECK(ci.nullable); i_found = true; } else if (ci.name == "j") { - CHECK(ci.type == soci::dt_int32); + CHECK(ci.type == soci::dt_integer); CHECK(ci.nullable); j_found = true; } @@ -806,24 +806,24 @@ TEST_CASE("PostgreSQL DDL with metadata", "[postgresql][ddl]") // (note: statement is executed when ddl object goes out of scope) { soci::ddl_type ddl = sql.create_table(ddl_t2); - ddl.column("i", soci::dt_int32); - ddl.column("j", soci::dt_int32); - ddl.column("k", soci::dt_int32)("not null"); + ddl.column("i", soci::dt_integer); + ddl.column("j", soci::dt_integer); + ddl.column("k", soci::dt_integer)("not null"); ddl.primary_key("t2_pk", "j"); } - sql.add_column(ddl_t1, "k", soci::dt_int32); + sql.add_column(ddl_t1, "k", soci::dt_integer); sql.add_column(ddl_t1, "big", soci::dt_string, 0); // "unlimited" length -> text sql.drop_column(ddl_t1, "i"); // or with constraint as in t2: - sql.add_column(ddl_t2, "m", soci::dt_int32)("not null"); + sql.add_column(ddl_t2, "m", soci::dt_integer)("not null"); // third table with a foreign key to the second one { soci::ddl_type ddl = sql.create_table(ddl_t3); - ddl.column("x", soci::dt_int32); - ddl.column("y", soci::dt_int32); + ddl.column("x", soci::dt_integer); + ddl.column("y", soci::dt_integer); ddl.foreign_key("t3_fk", "x", ddl_t2, "j"); } @@ -858,13 +858,13 @@ TEST_CASE("PostgreSQL DDL with metadata", "[postgresql][ddl]") { if (ci.name == "j") { - CHECK(ci.type == soci::dt_int32); + CHECK(ci.type == soci::dt_integer); CHECK(ci.nullable); j_found = true; } else if (ci.name == "k") { - CHECK(ci.type == soci::dt_int32); + CHECK(ci.type == soci::dt_integer); CHECK(ci.nullable); k_found = true; } @@ -899,25 +899,25 @@ TEST_CASE("PostgreSQL DDL with metadata", "[postgresql][ddl]") { if (ci.name == "i") { - CHECK(ci.type == soci::dt_int32); + CHECK(ci.type == soci::dt_integer); CHECK(ci.nullable); i_found = true; } else if (ci.name == "j") { - CHECK(ci.type == soci::dt_int32); + CHECK(ci.type == soci::dt_integer); CHECK(ci.nullable == false); // primary key j_found = true; } else if (ci.name == "k") { - CHECK(ci.type == soci::dt_int32); + CHECK(ci.type == soci::dt_integer); CHECK(ci.nullable == false); k_found = true; } else if (ci.name == "m") { - CHECK(ci.type == soci::dt_int32); + CHECK(ci.type == soci::dt_integer); CHECK(ci.nullable == false); m_found = true; } diff --git a/tests/sqlite3/test-sqlite3.cpp b/tests/sqlite3/test-sqlite3.cpp index 8636a96f7..ae322ce50 100644 --- a/tests/sqlite3/test-sqlite3.cpp +++ b/tests/sqlite3/test-sqlite3.cpp @@ -471,10 +471,10 @@ TEST_CASE("SQLite type inference", "[sqlite][sequence]") row const& r1 = (*it); CHECK(r1.get(0) == cvc); CHECK(r1.get(1) == Approx(cdec)); - CHECK(r1.get(2) == cll); - CHECK(r1.get(3) == cull); - CHECK(r1.get(4) == cll); - CHECK(r1.get(5) == cull); + CHECK(r1.get(2) == cll); + CHECK(r1.get(3) == cull); + CHECK(r1.get(4) == cll); + CHECK(r1.get(5) == cull); } } From 4e80322182d5374cee1d73a0137503b3cbeced3d Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Tue, 29 Nov 2022 12:35:38 +0100 Subject: [PATCH 24/46] Fix header include order --- include/soci/soci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/soci/soci.h b/include/soci/soci.h index 1968d0866..39fe0f939 100644 --- a/include/soci/soci.h +++ b/include/soci/soci.h @@ -15,9 +15,9 @@ #include "soci/blob-exchange.h" #include "soci/column-info.h" #include "soci/connection-pool.h" -#include "soci/fixed-size-ints.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" From d95c716232f9cb718abb71e849318918cd51cbef Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Tue, 29 Nov 2022 12:42:23 +0100 Subject: [PATCH 25/46] Remove abbreviation in user-facing ODBC error message --- src/backends/odbc/statement.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/odbc/statement.cpp b/src/backends/odbc/statement.cpp index 2f7a775e7..bcacf6604 100644 --- a/src/backends/odbc/statement.cpp +++ b/src/backends/odbc/statement.cpp @@ -359,7 +359,7 @@ void odbc_statement_backend::describe_column(int colNum, data_type & type, if (is_odbc_error(rc_colattr)) { std::ostringstream ss; - ss << "getting \"unsigned\" col attribute of the column at position " << colNum; + ss << "getting \"unsigned\" column attribute of the column at position " << colNum; throw odbc_soci_error(SQL_HANDLE_STMT, hstmt_, ss.str()); } From a824ac85028a56ba8e70882e721303d84c05665b Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Tue, 29 Nov 2022 12:45:58 +0100 Subject: [PATCH 26/46] Fix incorrect extraction of Postgres bool type bool values occupy 1 byte of storage in Postgres, so we might as well extract it as 1 byte instead of 4. --- docs/backends/postgresql.md | 3 ++- src/backends/postgresql/statement.cpp | 5 ++++- tests/postgresql/test-postgresql.cpp | 5 +++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/backends/postgresql.md b/docs/backends/postgresql.md index 30682a541..ce3519138 100644 --- a/docs/backends/postgresql.md +++ b/docs/backends/postgresql.md @@ -91,8 +91,9 @@ When calling `row::get()`, the type you should pass as `T` depends upon the u | PostgreSQL Data Type | SOCI Data Type | `row::get` specializations | | ------------------------------------------------------------ | -------------- | ----------------------------- | | numeric, real, double | dt_double | double | +| boolean | dt_int8 | int8_t | | smallint | dt_int16 | int16_t | -| boolean, integer | dt_int32 | int32_t | +| integer | dt_int32 | int32_t | | int8 | dt_int64 | int64_t | | oid | dt_int32 | int32_t | | char, varchar, text, cstring, bpchar | dt_string | std::string | diff --git a/src/backends/postgresql/statement.cpp b/src/backends/postgresql/statement.cpp index 026ad7b99..abd2a68cf 100644 --- a/src/backends/postgresql/statement.cpp +++ b/src/backends/postgresql/statement.cpp @@ -783,11 +783,14 @@ void postgresql_statement_backend::describe_column(int colNum, data_type & type, type = dt_double; break; + case 16: // bool + type = dt_int8; + break; + case 21: // int2 type = dt_int16; break; - case 16: // bool case 23: // int4 case 26: // oid type = dt_int32; diff --git a/tests/postgresql/test-postgresql.cpp b/tests/postgresql/test-postgresql.cpp index 5a583f864..768908b52 100644 --- a/tests/postgresql/test-postgresql.cpp +++ b/tests/postgresql/test-postgresql.cpp @@ -369,13 +369,18 @@ TEST_CASE("PostgreSQL boolean", "[postgresql][boolean]") sql << "insert into soci_test(val) values(:val)", use(i1); int i2 = 7; + row r; sql << "select val from soci_test", into(i2); + sql << "select val from soci_test", into(r); CHECK(i2 == i1); + CHECK(r.get(0) == i1); sql << "update soci_test set val = true"; sql << "select val from soci_test", into(i2); + sql << "select val from soci_test", into(r); CHECK(i2 == 1); + CHECK(r.get(0) == 1); } struct uuid_table_creator : table_creator_base From ede341c26740e0a1e0f7495975d717a845517b10 Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Sat, 31 Dec 2022 14:16:40 +0100 Subject: [PATCH 27/46] Remove unnecessary type casts --- src/backends/mysql/standard-use-type.cpp | 18 ++++++------------ src/backends/mysql/vector-use-type.cpp | 18 ++++++------------ src/backends/postgresql/standard-use-type.cpp | 18 ++++++------------ src/backends/postgresql/vector-use-type.cpp | 18 ++++++------------ 4 files changed, 24 insertions(+), 48 deletions(-) diff --git a/src/backends/mysql/standard-use-type.cpp b/src/backends/mysql/standard-use-type.cpp index 9f8cd35d8..17fe5d381 100644 --- a/src/backends/mysql/standard-use-type.cpp +++ b/src/backends/mysql/standard-use-type.cpp @@ -70,8 +70,7 @@ void mysql_standard_use_type_backend::pre_use(indicator const *ind) std::size_t const bufSize = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; - snprintf(buf_, bufSize, "%d", - static_cast(exchange_type_cast(data_))); + snprintf(buf_, bufSize, "%d", exchange_type_cast(data_)); } break; case x_uint8: @@ -79,8 +78,7 @@ void mysql_standard_use_type_backend::pre_use(indicator const *ind) std::size_t const bufSize = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; - snprintf(buf_, bufSize, "%u", - static_cast(exchange_type_cast(data_))); + snprintf(buf_, bufSize, "%u", exchange_type_cast(data_)); } break; case x_int16: @@ -88,8 +86,7 @@ void mysql_standard_use_type_backend::pre_use(indicator const *ind) std::size_t const bufSize = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; - snprintf(buf_, bufSize, "%d", - static_cast(exchange_type_cast(data_))); + snprintf(buf_, bufSize, "%d", exchange_type_cast(data_)); } break; case x_uint16: @@ -97,8 +94,7 @@ void mysql_standard_use_type_backend::pre_use(indicator const *ind) std::size_t const bufSize = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; - snprintf(buf_, bufSize, "%u", - static_cast(exchange_type_cast(data_))); + snprintf(buf_, bufSize, "%u", exchange_type_cast(data_)); } break; case x_int32: @@ -106,8 +102,7 @@ void mysql_standard_use_type_backend::pre_use(indicator const *ind) std::size_t const bufSize = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; - snprintf(buf_, bufSize, "%d", - static_cast(exchange_type_cast(data_))); + snprintf(buf_, bufSize, "%d", exchange_type_cast(data_)); } break; case x_uint32: @@ -115,8 +110,7 @@ void mysql_standard_use_type_backend::pre_use(indicator const *ind) std::size_t const bufSize = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; - snprintf(buf_, bufSize, "%u", - static_cast(exchange_type_cast(data_))); + snprintf(buf_, bufSize, "%u", exchange_type_cast(data_)); } break; case x_int64: diff --git a/src/backends/mysql/vector-use-type.cpp b/src/backends/mysql/vector-use-type.cpp index 144f23348..456f2a9b2 100644 --- a/src/backends/mysql/vector-use-type.cpp +++ b/src/backends/mysql/vector-use-type.cpp @@ -91,8 +91,7 @@ void mysql_vector_use_type_backend::pre_use(indicator const *ind) std::size_t const bufSize = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%d", - static_cast(v[i])); + snprintf(buf, bufSize, "%d", v[i]); } break; case x_uint8: @@ -104,8 +103,7 @@ void mysql_vector_use_type_backend::pre_use(indicator const *ind) std::size_t const bufSize = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%u", - static_cast(v[i])); + snprintf(buf, bufSize, "%u", v[i]); } break; case x_int16: @@ -117,8 +115,7 @@ void mysql_vector_use_type_backend::pre_use(indicator const *ind) std::size_t const bufSize = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%d", - static_cast(v[i])); + snprintf(buf, bufSize, "%d", v[i]); } break; case x_uint16: @@ -130,8 +127,7 @@ void mysql_vector_use_type_backend::pre_use(indicator const *ind) std::size_t const bufSize = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%u", - static_cast(v[i])); + snprintf(buf, bufSize, "%u", v[i]); } break; case x_int32: @@ -143,8 +139,7 @@ void mysql_vector_use_type_backend::pre_use(indicator const *ind) std::size_t const bufSize = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%d", - static_cast(v[i])); + snprintf(buf, bufSize, "%d", v[i]); } break; case x_uint32: @@ -156,8 +151,7 @@ void mysql_vector_use_type_backend::pre_use(indicator const *ind) std::size_t const bufSize = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%u", - static_cast(v[i])); + snprintf(buf, bufSize, "%u", v[i]); } break; case x_int64: diff --git a/src/backends/postgresql/standard-use-type.cpp b/src/backends/postgresql/standard-use-type.cpp index 9b454b551..9cff41eee 100644 --- a/src/backends/postgresql/standard-use-type.cpp +++ b/src/backends/postgresql/standard-use-type.cpp @@ -73,8 +73,7 @@ void postgresql_standard_use_type_backend::pre_use(indicator const * ind) std::size_t const bufSize = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; - snprintf(buf_, bufSize, "%d", - static_cast(exchange_type_cast(data_))); + snprintf(buf_, bufSize, "%d", exchange_type_cast(data_)); } break; case x_uint8: @@ -82,8 +81,7 @@ void postgresql_standard_use_type_backend::pre_use(indicator const * ind) std::size_t const bufSize = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; - snprintf(buf_, bufSize, "%u", - static_cast(exchange_type_cast(data_))); + snprintf(buf_, bufSize, "%u", exchange_type_cast(data_)); } break; case x_int16: @@ -91,8 +89,7 @@ void postgresql_standard_use_type_backend::pre_use(indicator const * ind) std::size_t const bufSize = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; - snprintf(buf_, bufSize, "%d", - static_cast(exchange_type_cast(data_))); + snprintf(buf_, bufSize, "%d", exchange_type_cast(data_)); } break; case x_uint16: @@ -100,8 +97,7 @@ void postgresql_standard_use_type_backend::pre_use(indicator const * ind) std::size_t const bufSize = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; - snprintf(buf_, bufSize, "%u", - static_cast(exchange_type_cast(data_))); + snprintf(buf_, bufSize, "%u", exchange_type_cast(data_)); } break; case x_int32: @@ -109,8 +105,7 @@ void postgresql_standard_use_type_backend::pre_use(indicator const * ind) std::size_t const bufSize = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; - snprintf(buf_, bufSize, "%d", - static_cast(exchange_type_cast(data_))); + snprintf(buf_, bufSize, "%d", exchange_type_cast(data_)); } break; case x_uint32: @@ -118,8 +113,7 @@ void postgresql_standard_use_type_backend::pre_use(indicator const * ind) std::size_t const bufSize = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; - snprintf(buf_, bufSize, "%u", - static_cast(exchange_type_cast(data_))); + snprintf(buf_, bufSize, "%u", exchange_type_cast(data_)); } break; case x_int64: diff --git a/src/backends/postgresql/vector-use-type.cpp b/src/backends/postgresql/vector-use-type.cpp index a0aa34965..332b7ebab 100644 --- a/src/backends/postgresql/vector-use-type.cpp +++ b/src/backends/postgresql/vector-use-type.cpp @@ -108,8 +108,7 @@ void postgresql_vector_use_type_backend::pre_use(indicator const * ind) std::size_t const bufSize = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%d", - static_cast(v[i])); + snprintf(buf, bufSize, "%d", v[i]); } break; case x_uint8: @@ -121,8 +120,7 @@ void postgresql_vector_use_type_backend::pre_use(indicator const * ind) std::size_t const bufSize = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%u", - static_cast(v[i])); + snprintf(buf, bufSize, "%u", v[i]); } break; case x_int16: @@ -134,8 +132,7 @@ void postgresql_vector_use_type_backend::pre_use(indicator const * ind) std::size_t const bufSize = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%d", - static_cast(v[i])); + snprintf(buf, bufSize, "%d", v[i]); } break; case x_uint16: @@ -147,8 +144,7 @@ void postgresql_vector_use_type_backend::pre_use(indicator const * ind) std::size_t const bufSize = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%u", - static_cast(v[i])); + snprintf(buf, bufSize, "%u", v[i]); } break; case x_int32: @@ -160,8 +156,7 @@ void postgresql_vector_use_type_backend::pre_use(indicator const * ind) std::size_t const bufSize = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%d", - static_cast(v[i])); + snprintf(buf, bufSize, "%d", v[i]); } break; case x_uint32: @@ -173,8 +168,7 @@ void postgresql_vector_use_type_backend::pre_use(indicator const * ind) std::size_t const bufSize = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%u", - static_cast(v[i])); + snprintf(buf, bufSize, "%u", v[i]); } break; case x_int64: From 60da2f0a44bb1cbbccbf533121d3b2280d652eef Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Sat, 31 Dec 2022 12:32:57 +0100 Subject: [PATCH 28/46] Merge separate integer unit tests into one --- tests/common-tests.h | 388 ++++++++++++++++++++----------------------- 1 file changed, 180 insertions(+), 208 deletions(-) diff --git a/tests/common-tests.h b/tests/common-tests.h index 033148f35..c0adbac0e 100644 --- a/tests/common-tests.h +++ b/tests/common-tests.h @@ -1524,74 +1524,67 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") SECTION("int8_t") { - int8_t s = 123; - sql << "insert into soci_test(id) values(:id)", use(s); + int8_t i = 123; + sql << "insert into soci_test(id) values(:id)", use(i); - int8_t s2 = 0; - sql << "select id from soci_test", into(s2); + int8_t i2 = 0; + sql << "select id from soci_test", into(i2); - CHECK(s2 == 123); - } + CHECK(i2 == 123); - SECTION("int8_t min") - { - if (!tc_.has_full_int8_support()) + if (tc_.has_full_int8_support()) { - WARN("int8 not fully supported by the database, skipping the test."); - return; - } + sql << "delete from soci_test"; - int8_t s = (std::numeric_limits::min)(); - sql << "insert into soci_test(id) values(:id)", use(s); + i = (std::numeric_limits::min)(); + sql << "insert into soci_test(id) values(:id)", use(i); - int8_t s2 = 0; - sql << "select id from soci_test", into(s2); + i2 = 0; + sql << "select id from soci_test", into(i2); - CHECK(s2 == (std::numeric_limits::min)()); - } + CHECK(i2 == (std::numeric_limits::min)()); + } - SECTION("int8_t max") - { - int8_t s = (std::numeric_limits::max)(); - sql << "insert into soci_test(id) values(:id)", use(s); + sql << "delete from soci_test"; - int8_t s2 = 0; - sql << "select id from soci_test", into(s2); + i = (std::numeric_limits::max)(); + sql << "insert into soci_test(id) values(:id)", use(i); + + i2 = 0; + sql << "select id from soci_test", into(i2); - CHECK(s2 == (std::numeric_limits::max)()); + CHECK(i2 == (std::numeric_limits::max)()); } SECTION("uint8_t") { - uint8_t s = 123; - sql << "insert into soci_test(id) values(:id)", use(s); + uint8_t ui = 123; + sql << "insert into soci_test(id) values(:id)", use(ui); - uint8_t s2 = 0; - sql << "select id from soci_test", into(s2); + uint8_t ui2 = 0; + sql << "select id from soci_test", into(ui2); - CHECK(s2 == 123); - } + CHECK(ui2 == 123); - SECTION("uint8_t min") - { - uint8_t s = (std::numeric_limits::min)(); - sql << "insert into soci_test(id) values(:id)", use(s); + sql << "delete from soci_test"; - uint8_t s2 = 0; - sql << "select id from soci_test", into(s2); + ui = (std::numeric_limits::min)(); + sql << "insert into soci_test(id) values(:id)", use(ui); - CHECK(s2 == (std::numeric_limits::min)()); - } + ui2 = 0; + sql << "select id from soci_test", into(ui2); - SECTION("uint8_t max") - { - uint8_t s = (std::numeric_limits::max)(); - sql << "insert into soci_test(id) values(:id)", use(s); + CHECK(ui2 == (std::numeric_limits::min)()); - uint8_t s2 = 0; - sql << "select id from soci_test", into(s2); + sql << "delete from soci_test"; - CHECK(s2 == (std::numeric_limits::max)()); + ui = (std::numeric_limits::max)(); + sql << "insert into soci_test(id) values(:id)", use(ui); + + ui2 = 0; + sql << "select id from soci_test", into(ui2); + + CHECK(ui2 == (std::numeric_limits::max)()); } SECTION("short") @@ -1607,74 +1600,67 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") SECTION("int16_t") { - int16_t s = 123; - sql << "insert into soci_test(id) values(:id)", use(s); + int16_t i = 123; + sql << "insert into soci_test(id) values(:id)", use(i); - int16_t s2 = 0; - sql << "select id from soci_test", into(s2); + int16_t i2 = 0; + sql << "select id from soci_test", into(i2); - CHECK(s2 == 123); - } + CHECK(i2 == 123); - SECTION("int16_t min") - { - int16_t s = (std::numeric_limits::min)(); - sql << "insert into soci_test(id) values(:id)", use(s); + sql << "delete from soci_test"; - int16_t s2 = 0; - sql << "select id from soci_test", into(s2); + i = (std::numeric_limits::min)(); + sql << "insert into soci_test(id) values(:id)", use(i); - CHECK(s2 == (std::numeric_limits::min)()); - } + i2 = 0; + sql << "select id from soci_test", into(i2); - SECTION("int16_t max") - { - int16_t s = (std::numeric_limits::max)(); - sql << "insert into soci_test(id) values(:id)", use(s); + CHECK(i2 == (std::numeric_limits::min)()); - int16_t s2 = 0; - sql << "select id from soci_test", into(s2); + sql << "delete from soci_test"; + + i = (std::numeric_limits::max)(); + sql << "insert into soci_test(id) values(:id)", use(i); - CHECK(s2 == (std::numeric_limits::max)()); + i2 = 0; + sql << "select id from soci_test", into(i2); + + CHECK(i2 == (std::numeric_limits::max)()); } SECTION("uint16_t") { - uint16_t s = 123; - sql << "insert into soci_test(id) values(:id)", use(s); + uint16_t ui = 123; + sql << "insert into soci_test(id) values(:id)", use(ui); - uint16_t s2 = 0; - sql << "select id from soci_test", into(s2); + uint16_t ui2 = 0; + sql << "select id from soci_test", into(ui2); - CHECK(s2 == 123); - } + CHECK(ui2 == 123); - SECTION("uint16_t min") - { - uint16_t s = (std::numeric_limits::min)(); - sql << "insert into soci_test(id) values(:id)", use(s); + sql << "delete from soci_test"; - uint16_t s2 = 0; - sql << "select id from soci_test", into(s2); + ui = (std::numeric_limits::min)(); + sql << "insert into soci_test(id) values(:id)", use(ui); - CHECK(s2 == (std::numeric_limits::min)()); - } + ui2 = 0; + sql << "select id from soci_test", into(ui2); - SECTION("uint16_t max") - { - if (!tc_.has_full_unsigned_type_support()) + CHECK(ui2 == (std::numeric_limits::min)()); + + if (tc_.has_full_unsigned_type_support()) { - WARN("uint16 not fully supported by the database, skipping the test."); - return; - } + sql << "delete from soci_test"; - uint16_t s = (std::numeric_limits::max)(); - sql << "insert into soci_test(id) values(:id)", use(s); + ui = (std::numeric_limits::max)(); + sql << "insert into soci_test(id) values(:id)", use(ui); - uint16_t s2 = 0; - sql << "select id from soci_test", into(s2); + ui2 = 0; + sql << "select id from soci_test", into(ui2); - CHECK(s2 == (std::numeric_limits::max)()); + CHECK(ui2 == (std::numeric_limits::max)()); + } } SECTION("int") @@ -1697,25 +1683,23 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") sql << "select id from soci_test", into(i2); CHECK(i2 == -12345678); - } - SECTION("int32_t min") - { - int32_t i = (std::numeric_limits::min)(); + sql << "delete from soci_test"; + + i = (std::numeric_limits::min)(); sql << "insert into soci_test(id) values(:i)", use(i); - int32_t i2 = 0; + i2 = 0; sql << "select id from soci_test", into(i2); CHECK(i2 == (std::numeric_limits::min)()); - } - SECTION("int32_t max") - { - int32_t i = (std::numeric_limits::max)(); + sql << "delete from soci_test"; + + i = (std::numeric_limits::max)(); sql << "insert into soci_test(id) values(:i)", use(i); - int32_t i2 = 0; + i2 = 0; sql << "select id from soci_test", into(i2); CHECK(i2 == (std::numeric_limits::max)()); @@ -1723,41 +1707,36 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") SECTION("uint32_t") { - uint32_t i = 12345678; - sql << "insert into soci_test(id) values(:i)", use(i); + uint32_t ui = 12345678; + sql << "insert into soci_test(id) values(:i)", use(ui); - uint32_t i2 = 0; - sql << "select id from soci_test", into(i2); + uint32_t ui2 = 0; + sql << "select id from soci_test", into(ui2); - CHECK(i2 == 12345678); - } + CHECK(ui2 == 12345678); - SECTION("uint32_t min") - { - uint32_t i = (std::numeric_limits::min)(); - sql << "insert into soci_test(id) values(:i)", use(i); + sql << "delete from soci_test"; - uint32_t i2 = 0; - sql << "select id from soci_test", into(i2); + ui = (std::numeric_limits::min)(); + sql << "insert into soci_test(id) values(:i)", use(ui); - CHECK(i2 == (std::numeric_limits::min)()); - } + ui2 = 0; + sql << "select id from soci_test", into(ui2); - SECTION("uint32_t max") - { - if (!tc_.has_full_unsigned_type_support()) + CHECK(ui2 == (std::numeric_limits::min)()); + + if (tc_.has_full_unsigned_type_support()) { - WARN("uint32 not fully supported by the database, skipping the test."); - return; - } + sql << "delete from soci_test"; - uint32_t i = (std::numeric_limits::max)(); - sql << "insert into soci_test(ul) values(:i)", use(i); + ui = (std::numeric_limits::max)(); + sql << "insert into soci_test(ul) values(:i)", use(ui); - uint32_t i2 = 0; - sql << "select ul from soci_test", into(i2); + ui2 = 0; + sql << "select ul from soci_test", into(ui2); - CHECK(i2 == (std::numeric_limits::max)()); + CHECK(ui2 == (std::numeric_limits::max)()); + } } SECTION("unsigned long") @@ -1779,74 +1758,67 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") SECTION("int64_t") { - int64_t ll = 4000000000ll; - sql << "insert into soci_test(ll) values(:num)", use(ll); + int64_t i = 4000000000ll; + sql << "insert into soci_test(ll) values(:num)", use(i); - int64_t ll2 = 0; - sql << "select ll from soci_test", into(ll2); + int64_t i2 = 0; + sql << "select ll from soci_test", into(i2); - CHECK(ll2 == 4000000000ll); - } + CHECK(i2 == 4000000000ll); - SECTION("int64_t min") - { - int64_t ll = (std::numeric_limits::min)(); - sql << "insert into soci_test(ll) values(:num)", use(ll); + sql << "delete from soci_test"; - int64_t ll2 = 0; - sql << "select ll from soci_test", into(ll2); + i = (std::numeric_limits::min)(); + sql << "insert into soci_test(ll) values(:num)", use(i); - CHECK(ll2 == (std::numeric_limits::min)()); - } + i2 = 0; + sql << "select ll from soci_test", into(i2); - SECTION("int64_t max") - { - int64_t ll = (std::numeric_limits::max)(); - sql << "insert into soci_test(ll) values(:num)", use(ll); + CHECK(i2 == (std::numeric_limits::min)()); - int64_t ll2 = 0; - sql << "select ll from soci_test", into(ll2); + sql << "delete from soci_test"; + + i = (std::numeric_limits::max)(); + sql << "insert into soci_test(ll) values(:num)", use(i); + + i2 = 0; + sql << "select ll from soci_test", into(i2); - CHECK(ll2 == (std::numeric_limits::max)()); + CHECK(i2 == (std::numeric_limits::max)()); } SECTION("uint64_t") { - uint64_t ul = 4000000000ull; - sql << "insert into soci_test(ul) values(:num)", use(ul); + uint64_t ui = 4000000000ull; + sql << "insert into soci_test(ul) values(:num)", use(ui); - uint64_t ul2 = 0; - sql << "select ul from soci_test", into(ul2); + uint64_t ui2 = 0; + sql << "select ul from soci_test", into(ui2); - CHECK(ul2 == 4000000000ull); - } + CHECK(ui2 == 4000000000ull); - SECTION("uint64_t min") - { - uint64_t ul = (std::numeric_limits::min)(); - sql << "insert into soci_test(ul) values(:num)", use(ul); + sql << "delete from soci_test"; - uint64_t ul2 = 0; - sql << "select ul from soci_test", into(ul2); + ui = (std::numeric_limits::min)(); + sql << "insert into soci_test(ul) values(:num)", use(ui); - CHECK(ul2 == (std::numeric_limits::min)()); - } + ui2 = 0; + sql << "select ul from soci_test", into(ui2); - SECTION("uint64_t max") - { - if (!tc_.has_full_unsigned_type_support() || !tc_.has_full_uint64_support()) + CHECK(ui2 == (std::numeric_limits::min)()); + + if (tc_.has_full_unsigned_type_support() && tc_.has_full_uint64_support()) { - WARN("uint64 not fully supported by the database, skipping the test."); - return; - } + sql << "delete from soci_test"; - uint64_t ul = (std::numeric_limits::max)(); - sql << "insert into soci_test(ul) values(:num)", use(ul); + ui = (std::numeric_limits::max)(); + sql << "insert into soci_test(ul) values(:num)", use(ui); - uint64_t ul2 = 0; - sql << "select ul from soci_test", into(ul2); + ui2 = 0; + sql << "select ul from soci_test", into(ui2); - CHECK(ul2 == (std::numeric_limits::max)()); + CHECK(ui2 == (std::numeric_limits::max)()); + } } SECTION("double") @@ -1937,24 +1909,24 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") SECTION("const int8_t") { - int8_t const s = 123; - sql << "insert into soci_test(id) values(:id)", use(s); + int8_t const i = 123; + sql << "insert into soci_test(id) values(:id)", use(i); - int8_t s2 = 0; - sql << "select id from soci_test", into(s2); + int8_t i2 = 0; + sql << "select id from soci_test", into(i2); - CHECK(s2 == 123); + CHECK(i2 == 123); } SECTION("const uint8_t") { - uint8_t const s = 123; - sql << "insert into soci_test(id) values(:id)", use(s); + uint8_t const ui = 123; + sql << "insert into soci_test(id) values(:id)", use(ui); - uint8_t s2 = 0; - sql << "select id from soci_test", into(s2); + uint8_t ui2 = 0; + sql << "select id from soci_test", into(ui2); - CHECK(s2 == 123); + CHECK(ui2 == 123); } SECTION("const short") @@ -1970,24 +1942,24 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") SECTION("const int16_t") { - int16_t const s = 123; - sql << "insert into soci_test(id) values(:id)", use(s); + int16_t const i = 123; + sql << "insert into soci_test(id) values(:id)", use(i); - int16_t s2 = 0; - sql << "select id from soci_test", into(s2); + int16_t i2 = 0; + sql << "select id from soci_test", into(i2); - CHECK(s2 == 123); + CHECK(i2 == 123); } SECTION("const uint16_t") { - uint16_t const s = 123; - sql << "insert into soci_test(id) values(:id)", use(s); + uint16_t const ui = 123; + sql << "insert into soci_test(id) values(:id)", use(ui); - uint16_t s2 = 0; - sql << "select id from soci_test", into(s2); + uint16_t ui2 = 0; + sql << "select id from soci_test", into(ui2); - CHECK(s2 == 123); + CHECK(ui2 == 123); } SECTION("const int") @@ -2014,13 +1986,13 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") SECTION("const uint32_t") { - uint32_t const i = 12345678; - sql << "insert into soci_test(id) values(:i)", use(i); + uint32_t const ui = 12345678; + sql << "insert into soci_test(id) values(:i)", use(ui); - uint32_t i2 = 0; - sql << "select id from soci_test", into(i2); + uint32_t ui2 = 0; + sql << "select id from soci_test", into(ui2); - CHECK(i2 == 12345678); + CHECK(ui2 == 12345678); } SECTION("const unsigned long") @@ -2042,24 +2014,24 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") SECTION("const int64_t") { - int64_t const ul = 4000000000ll; - sql << "insert into soci_test(ul) values(:num)", use(ul); + int64_t const i = 4000000000ll; + sql << "insert into soci_test(ul) values(:num)", use(i); - int64_t ul2 = 0; - sql << "select ul from soci_test", into(ul2); + int64_t i2 = 0; + sql << "select ul from soci_test", into(i2); - CHECK(ul2 == 4000000000ll); + CHECK(i2 == 4000000000ll); } SECTION("const uint64_t") { - uint64_t const ul = 4000000000ull; - sql << "insert into soci_test(ul) values(:num)", use(ul); + uint64_t const ui = 4000000000ull; + sql << "insert into soci_test(ul) values(:num)", use(ui); - uint64_t ul2 = 0; - sql << "select ul from soci_test", into(ul2); + uint64_t ui2 = 0; + sql << "select ul from soci_test", into(ui2); - CHECK(ul2 == 4000000000ull); + CHECK(ui2 == 4000000000ull); } SECTION("const double") From 4c362139283c736effdcc956e9cd2e7d6ffd4728 Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Sat, 31 Dec 2022 12:44:59 +0100 Subject: [PATCH 29/46] Remove unsigned type support checks in unit tests Despite previously assumed and tested, most of the databases support storing the various unsigned integer values. The checks for it in the tests are therefore obsolete. Only Firebird and SQLite seem to have a problem with storing UINT64_MAX. The retrieval of it in a sorted result set with multiple other values shows that the value is stored as a signed integer in the database. --- tests/common-tests.h | 164 +++++++-------------------- tests/db2/test-db2.cpp | 5 - tests/firebird/test-firebird.cpp | 5 - tests/odbc/test-odbc-db2.cpp | 5 - tests/odbc/test-odbc-mssql.cpp | 29 ----- tests/odbc/test-odbc-mysql.cpp | 19 +--- tests/odbc/test-odbc-postgresql.cpp | 5 - tests/postgresql/test-postgresql.cpp | 5 - tests/sqlite3/test-sqlite3.cpp | 5 - 9 files changed, 41 insertions(+), 201 deletions(-) diff --git a/tests/common-tests.h b/tests/common-tests.h index c0adbac0e..5aa937f9e 100644 --- a/tests/common-tests.h +++ b/tests/common-tests.h @@ -462,15 +462,6 @@ class test_context_base // to fit by default. virtual bool has_silent_truncate_bug(session&) const { return false; } - // Override this if the backend doesn't fully support signed 8-bit integers. - virtual bool has_full_int8_support() const { return true; } - - // Override this if the backend doesn't support unsigned types. - virtual bool has_full_unsigned_type_support() const { return true; } - - // Override this if the backend doesn't fully support unsigned 64-bit integers. - virtual bool has_full_uint64_support() const { return true; } - // Override this if the backend doesn't distinguish between empty and null // strings (Oracle does this). virtual bool treats_empty_strings_as_null() const { return false; } @@ -1532,18 +1523,15 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") CHECK(i2 == 123); - if (tc_.has_full_int8_support()) - { - sql << "delete from soci_test"; + sql << "delete from soci_test"; - i = (std::numeric_limits::min)(); - sql << "insert into soci_test(id) values(:id)", use(i); + i = (std::numeric_limits::min)(); + sql << "insert into soci_test(id) values(:id)", use(i); - i2 = 0; - sql << "select id from soci_test", into(i2); + i2 = 0; + sql << "select id from soci_test", into(i2); - CHECK(i2 == (std::numeric_limits::min)()); - } + CHECK(i2 == (std::numeric_limits::min)()); sql << "delete from soci_test"; @@ -1649,18 +1637,15 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") CHECK(ui2 == (std::numeric_limits::min)()); - if (tc_.has_full_unsigned_type_support()) - { - sql << "delete from soci_test"; + sql << "delete from soci_test"; - ui = (std::numeric_limits::max)(); - sql << "insert into soci_test(id) values(:id)", use(ui); + ui = (std::numeric_limits::max)(); + sql << "insert into soci_test(id) values(:id)", use(ui); - ui2 = 0; - sql << "select id from soci_test", into(ui2); + ui2 = 0; + sql << "select id from soci_test", into(ui2); - CHECK(ui2 == (std::numeric_limits::max)()); - } + CHECK(ui2 == (std::numeric_limits::max)()); } SECTION("int") @@ -1725,28 +1710,19 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") CHECK(ui2 == (std::numeric_limits::min)()); - if (tc_.has_full_unsigned_type_support()) - { - sql << "delete from soci_test"; + sql << "delete from soci_test"; - ui = (std::numeric_limits::max)(); - sql << "insert into soci_test(ul) values(:i)", use(ui); + ui = (std::numeric_limits::max)(); + sql << "insert into soci_test(ul) values(:i)", use(ui); - ui2 = 0; - sql << "select ul from soci_test", into(ui2); + ui2 = 0; + sql << "select ul from soci_test", into(ui2); - CHECK(ui2 == (std::numeric_limits::max)()); - } + CHECK(ui2 == (std::numeric_limits::max)()); } SECTION("unsigned long") { - if (!tc_.has_full_unsigned_type_support()) - { - WARN("unsigned long not fully supported by the database, skipping the test."); - return; - } - unsigned long ul = 4000000000ul; sql << "insert into soci_test(ul) values(:num)", use(ul); @@ -1807,18 +1783,15 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") CHECK(ui2 == (std::numeric_limits::min)()); - if (tc_.has_full_unsigned_type_support() && tc_.has_full_uint64_support()) - { - sql << "delete from soci_test"; + sql << "delete from soci_test"; - ui = (std::numeric_limits::max)(); - sql << "insert into soci_test(ul) values(:num)", use(ui); + ui = (std::numeric_limits::max)(); + sql << "insert into soci_test(ul) values(:num)", use(ui); - ui2 = 0; - sql << "select ul from soci_test", into(ui2); + ui2 = 0; + sql << "select ul from soci_test", into(ui2); - CHECK(ui2 == (std::numeric_limits::max)()); - } + CHECK(ui2 == (std::numeric_limits::max)()); } SECTION("double") @@ -1997,12 +1970,6 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") SECTION("const unsigned long") { - if (!tc_.has_full_unsigned_type_support()) - { - WARN("unsigned long not fully supported by the database, skipping the test."); - return; - } - unsigned long const ul = 4000000000ul; sql << "insert into soci_test(ul) values(:num)", use(ul); @@ -2194,11 +2161,8 @@ TEST_CASE_METHOD(common_tests, "Use vector", "[core][use][vector]") SECTION("int8_t") { std::vector v; - if (tc_.has_full_int8_support()) - { - v.push_back((std::numeric_limits::min)()); - v.push_back(-5); - } + v.push_back((std::numeric_limits::min)()); + v.push_back(-5); v.push_back(123); v.push_back((std::numeric_limits::max)()); @@ -2207,20 +2171,11 @@ TEST_CASE_METHOD(common_tests, "Use vector", "[core][use][vector]") std::vector v2(4); sql << "select sh from soci_test order by sh", into(v2); - if (tc_.has_full_int8_support()) - { - CHECK(v2.size() == 4); - CHECK(v2[0] == (std::numeric_limits::min)()); - CHECK(v2[1] == -5); - CHECK(v2[2] == 123); - CHECK(v2[3] == (std::numeric_limits::max)()); - } - else - { - CHECK(v2.size() == 2); - CHECK(v2[0] == 123); - CHECK(v2[1] == (std::numeric_limits::max)()); - } + CHECK(v2.size() == 4); + CHECK(v2[0] == (std::numeric_limits::min)()); + CHECK(v2[1] == -5); + CHECK(v2[2] == 123); + CHECK(v2[3] == (std::numeric_limits::max)()); } SECTION("uint8_t") @@ -2289,31 +2244,18 @@ TEST_CASE_METHOD(common_tests, "Use vector", "[core][use][vector]") v.push_back((std::numeric_limits::min)()); v.push_back(6); v.push_back(123); - if (tc_.has_full_unsigned_type_support()) - { - v.push_back((std::numeric_limits::max)()); - } + v.push_back((std::numeric_limits::max)()); sql << "insert into soci_test(val) values(:val)", use(v); std::vector v2(4); sql << "select val from soci_test order by val", into(v2); - if (tc_.has_full_unsigned_type_support()) - { - CHECK(v2.size() == 4); - } - else - { - CHECK(v2.size() == 3); - } + CHECK(v2.size() == 4); CHECK(v2[0] == (std::numeric_limits::min)()); CHECK(v2[1] == 6); CHECK(v2[2] == 123); - if (tc_.has_full_unsigned_type_support()) - { - CHECK(v2[3] == (std::numeric_limits::max)()); - } + CHECK(v2[3] == (std::numeric_limits::max)()); } SECTION("int") @@ -2388,33 +2330,20 @@ TEST_CASE_METHOD(common_tests, "Use vector", "[core][use][vector]") v.push_back(1); v.push_back(123); v.push_back(1000); - if (tc_.has_full_unsigned_type_support()) - { - v.push_back((std::numeric_limits::max)()); - } + v.push_back((std::numeric_limits::max)()); sql << "insert into soci_test(ul) values(:ul)", use(v); std::vector v2(6); sql << "select ul from soci_test order by ul", into(v2); - if (tc_.has_full_unsigned_type_support()) - { - CHECK(v2.size() == 6); - } - else - { - CHECK(v2.size() == 5); - } + CHECK(v2.size() == 6); CHECK(v2[0] == (std::numeric_limits::min)()); CHECK(v2[1] == 0); CHECK(v2[2] == 1); CHECK(v2[3] == 123); CHECK(v2[4] == 1000); - if (tc_.has_full_unsigned_type_support()) - { - CHECK(v2[5] == (std::numeric_limits::max)()); - } + CHECK(v2[5] == (std::numeric_limits::max)()); } SECTION("unsigned long long") @@ -2469,33 +2398,20 @@ TEST_CASE_METHOD(common_tests, "Use vector", "[core][use][vector]") v.push_back(1); v.push_back(123); v.push_back(1000); - if (tc_.has_full_unsigned_type_support() && tc_.has_full_uint64_support()) - { - v.push_back((std::numeric_limits::max)()); - } + v.push_back((std::numeric_limits::max)()); sql << "insert into soci_test(ul) values(:ul)", use(v); std::vector v2(6); sql << "select ul from soci_test order by ul", into(v2); - if (tc_.has_full_unsigned_type_support() && tc_.has_full_uint64_support()) - { - CHECK(v2.size() == 6); - } - else - { - CHECK(v2.size() == 5); - } + CHECK(v2.size() == 6); CHECK(v2[0] == (std::numeric_limits::min)()); CHECK(v2[1] == 0); CHECK(v2[2] == 1); CHECK(v2[3] == 123); CHECK(v2[4] == 1000); - if (tc_.has_full_unsigned_type_support() && tc_.has_full_uint64_support()) - { - CHECK(v2[5] == (std::numeric_limits::max)()); - } + CHECK(v2[5] == (std::numeric_limits::max)()); } SECTION("double") diff --git a/tests/db2/test-db2.cpp b/tests/db2/test-db2.cpp index eaeb86df6..5501f1da1 100644 --- a/tests/db2/test-db2.cpp +++ b/tests/db2/test-db2.cpp @@ -91,11 +91,6 @@ class test_context :public test_context_base return new table_creator_for_get_affected_rows(s); } - bool has_full_uint64_support() const override - { - return false; - } - std::string to_date_time(std::string const & pi_datdt_string) const override { return "to_date('" + pi_datdt_string + "', 'YYYY-MM-DD HH24:MI:SS')"; diff --git a/tests/firebird/test-firebird.cpp b/tests/firebird/test-firebird.cpp index 49f59185d..3e684c9c8 100644 --- a/tests/firebird/test-firebird.cpp +++ b/tests/firebird/test-firebird.cpp @@ -1334,11 +1334,6 @@ class test_context : public tests::test_context_base return new TableCreatorXML(s); } - bool has_full_uint64_support() const override - { - return false; - } - std::string to_date_time(std::string const &datdt_string) const override { return "'" + datdt_string + "'"; diff --git a/tests/odbc/test-odbc-db2.cpp b/tests/odbc/test-odbc-db2.cpp index b828cc27f..91788949e 100644 --- a/tests/odbc/test-odbc-db2.cpp +++ b/tests/odbc/test-odbc-db2.cpp @@ -89,11 +89,6 @@ class test_context : public test_context_base return new table_creator_for_get_affected_rows(s); } - bool has_full_uint64_support() const override - { - return false; - } - std::string to_date_time(std::string const &datdt_string) const { return "\'" + datdt_string + "\'"; diff --git a/tests/odbc/test-odbc-mssql.cpp b/tests/odbc/test-odbc-mssql.cpp index 5d51076b3..8b3ecd740 100644 --- a/tests/odbc/test-odbc-mssql.cpp +++ b/tests/odbc/test-odbc-mssql.cpp @@ -210,35 +210,6 @@ class test_context : public test_context_base return true; } - bool has_full_int8_support() const override - { - // MS SQL only supports tinyint values in the range [0..255]. - return false; - } - - bool has_full_unsigned_type_support() const override - { - // MS SQL only supports signed integer types. A direct mapping to - // e.g. a uint32 value is therefore only possible up to its equivalent - // signed type range. - // - // In the past, when tests used unsigned types, an overflow happened - // on the C++ side, effectively storing a negative value in the database. - // When reading this value back to an unsigned value, another overflow - // on the C++ side lead to the correct result in the unsigned type var. - // Since SOCI's full support of fixed-size C++ integers and the - // corresponding changes in database communication, unsigned types would - // get stored as-is without any overflows on the C++ side. As MS SQL - // doesn't support unsigned types, we get an overflow and an insertion - // error there. - return false; - } - - bool has_full_uint64_support() const override - { - return has_full_unsigned_type_support(); - } - std::string sql_length(std::string const& s) const override { return "len(" + s + ")"; diff --git a/tests/odbc/test-odbc-mysql.cpp b/tests/odbc/test-odbc-mysql.cpp index bdc67ed36..9ea70adf6 100644 --- a/tests/odbc/test-odbc-mysql.cpp +++ b/tests/odbc/test-odbc-mysql.cpp @@ -16,23 +16,6 @@ std::string connectString; backend_factory const &backEnd = *soci::factory_odbc(); -class test_context_odbc_mysql : public test_context -{ -public: - test_context_odbc_mysql(backend_factory const &backEnd_, - std::string const &connectString_) - : test_context(backEnd_, connectString_) {} - - bool has_full_uint64_support() const override - { - // For some reason it seems that MySQL has a bug under ODBC with which - // the maximum value of a uint64_t cannot be stored in and retrieved - // from the database. I.e. when storing 18446744073709551615, you're - // retrieving the value 9223372036854775807. - return false; - } -}; - int main(int argc, char** argv) { #ifdef _MSC_VER @@ -60,7 +43,7 @@ int main(int argc, char** argv) connectString = "FILEDSN=./test-mysql.dsn"; } - test_context_odbc_mysql tc(backEnd, connectString); + test_context tc(backEnd, connectString); return Catch::Session().run(argc, argv); } diff --git a/tests/odbc/test-odbc-postgresql.cpp b/tests/odbc/test-odbc-postgresql.cpp index 1fcf628e7..4dbfa3c46 100644 --- a/tests/odbc/test-odbc-postgresql.cpp +++ b/tests/odbc/test-odbc-postgresql.cpp @@ -212,11 +212,6 @@ class test_context : public test_context_base return !m_verDriver.is_initialized() || m_verDriver < odbc_version(9, 3, 400); } - bool has_full_uint64_support() const override - { - return false; - } - std::string fix_crlf_if_necessary(std::string const& s) const override { // Version 9.03.0300 (ancient, but still used on AppVeyor CI) is known diff --git a/tests/postgresql/test-postgresql.cpp b/tests/postgresql/test-postgresql.cpp index 768908b52..2dbf28b5d 100644 --- a/tests/postgresql/test-postgresql.cpp +++ b/tests/postgresql/test-postgresql.cpp @@ -1424,11 +1424,6 @@ class test_context : public test_context_base return false; } - bool has_full_uint64_support() const override - { - return false; - } - std::string sql_length(std::string const& s) const override { return "char_length(" + s + ")"; diff --git a/tests/sqlite3/test-sqlite3.cpp b/tests/sqlite3/test-sqlite3.cpp index ae322ce50..1b609a0da 100644 --- a/tests/sqlite3/test-sqlite3.cpp +++ b/tests/sqlite3/test-sqlite3.cpp @@ -665,11 +665,6 @@ class test_context : public test_context_base return true; } - bool has_full_uint64_support() const override - { - return false; - } - bool enable_std_char_padding(soci::session&) const override { // SQLite does not support right padded char type. From 88e2cb4ae58577206aedf7a7a97d45a2a9525bef Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Tue, 3 Jan 2023 21:35:14 +0100 Subject: [PATCH 30/46] Fix uint64 vector unit tests Firebird and SQLite store UINT64_MAX incorrectly, leading to an incorrect value ordering when retrieving sorted table contents. --- tests/common-tests.h | 29 +++++++++++++++++++++++------ tests/firebird/test-firebird.cpp | 11 +++++++++++ tests/sqlite3/test-sqlite3.cpp | 7 +++++++ 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/tests/common-tests.h b/tests/common-tests.h index 5aa937f9e..1f8cfcc5a 100644 --- a/tests/common-tests.h +++ b/tests/common-tests.h @@ -466,6 +466,11 @@ class test_context_base // strings (Oracle does this). virtual bool treats_empty_strings_as_null() const { return false; } + // Override this if the backend does not store values bigger than INT64_MAX + // correctly. This can lead to an unexpected ordering of values as larger + // values might be stored as overflown and therefore negative integer. + virtual bool has_uint64_storage_bug() const { return false; } + // Override this to call commit() if it's necessary for the DDL statements // to be taken into account (currently this is only the case for Firebird). virtual void on_after_ddl(session&) const { } @@ -2406,12 +2411,24 @@ TEST_CASE_METHOD(common_tests, "Use vector", "[core][use][vector]") sql << "select ul from soci_test order by ul", into(v2); CHECK(v2.size() == 6); - CHECK(v2[0] == (std::numeric_limits::min)()); - CHECK(v2[1] == 0); - CHECK(v2[2] == 1); - CHECK(v2[3] == 123); - CHECK(v2[4] == 1000); - CHECK(v2[5] == (std::numeric_limits::max)()); + if (tc_.has_uint64_storage_bug()) + { + CHECK(v2[0] == (std::numeric_limits::max)()); + CHECK(v2[1] == (std::numeric_limits::min)()); + CHECK(v2[2] == 0); + CHECK(v2[3] == 1); + CHECK(v2[4] == 123); + CHECK(v2[5] == 1000); + } + else + { + CHECK(v2[0] == (std::numeric_limits::min)()); + CHECK(v2[1] == 0); + CHECK(v2[2] == 1); + CHECK(v2[3] == 123); + CHECK(v2[4] == 1000); + CHECK(v2[5] == (std::numeric_limits::max)()); + } } SECTION("double") diff --git a/tests/firebird/test-firebird.cpp b/tests/firebird/test-firebird.cpp index 3e684c9c8..7c8b58a1c 100644 --- a/tests/firebird/test-firebird.cpp +++ b/tests/firebird/test-firebird.cpp @@ -1339,6 +1339,17 @@ class test_context : public tests::test_context_base return "'" + datdt_string + "'"; } + bool has_uint64_storage_bug() const override + { + // Firebird does not support unsigned integer types. + // We're using Firebird 3, which does not yet support a data + // type that can correctly store a UINT64_MAX. The biggest + // numeric data type available is numeric(18,0). + // Firebird 4 introduces the data type int128 and numeric(36,0), + // which will be sufficient for that in the future. + return true; + } + void on_after_ddl(soci::session& sql) const override { sql.commit(); diff --git a/tests/sqlite3/test-sqlite3.cpp b/tests/sqlite3/test-sqlite3.cpp index 1b609a0da..3d2ada131 100644 --- a/tests/sqlite3/test-sqlite3.cpp +++ b/tests/sqlite3/test-sqlite3.cpp @@ -665,6 +665,13 @@ class test_context : public test_context_base return true; } + bool has_uint64_storage_bug() const override + { + // SQLite processes integers as 8-byte signed values. Values bigger + // than INT64_MAX therefore overflow and are stored as negative values. + return true; + } + bool enable_std_char_padding(soci::session&) const override { // SQLite does not support right padded char type. From ea4ce9dd8f632b026f038aec6734f240371aa62d Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Fri, 30 Dec 2022 13:09:48 +0100 Subject: [PATCH 31/46] Simplify platform-specific data type defines The currently used preprocessor defines used to distinguish between platforms and defining the corresponding type_conversion/exchange_traits was found in multiple files. The logic of it is now put in a single place with custom defines to be used instead. --- include/soci/exchange-traits.h | 17 ++++++------ include/soci/fixed-size-ints.h | 49 +++++++++++++++++----------------- include/soci/soci-platform.h | 19 +++++++++++++ include/soci/soci-types.h | 15 +++++++++++ 4 files changed, 66 insertions(+), 34 deletions(-) create mode 100644 include/soci/soci-types.h diff --git a/include/soci/exchange-traits.h b/include/soci/exchange-traits.h index d70de2e26..068571daf 100644 --- a/include/soci/exchange-traits.h +++ b/include/soci/exchange-traits.h @@ -8,6 +8,7 @@ #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" @@ -99,17 +100,17 @@ struct exchange_traits enum { x_type = x_uint64 }; }; -#if defined(_WIN64) +#if defined(SOCI_INT64_IS_LONG) template <> -struct exchange_traits : exchange_traits +struct exchange_traits : exchange_traits { }; template <> -struct exchange_traits : exchange_traits +struct exchange_traits : exchange_traits { }; -#elif defined(__APPLE__) +#elif defined(SOCI_LONG_IS_64_BIT) template <> struct exchange_traits : exchange_traits { @@ -119,18 +120,16 @@ template <> struct exchange_traits : exchange_traits { }; -#elif defined(__LP64__) || (__WORDSIZE == 64) +#else template <> -struct exchange_traits : exchange_traits +struct exchange_traits : exchange_traits { }; template <> -struct exchange_traits : exchange_traits +struct exchange_traits : exchange_traits { }; -#else -#error "Unhandled type architecture" #endif template <> diff --git a/include/soci/fixed-size-ints.h b/include/soci/fixed-size-ints.h index 59aab9f81..fcdcef44d 100644 --- a/include/soci/fixed-size-ints.h +++ b/include/soci/fixed-size-ints.h @@ -1,6 +1,7 @@ #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 @@ -15,23 +16,23 @@ namespace soci // long and long long. With the following type_conversion specializations, // this becomes possible. -#if defined(_WIN64) +#if defined(SOCI_INT64_IS_LONG) template <> -struct type_conversion +struct type_conversion { - typedef int32_t base_type; + typedef int64_t base_type; - static void from_base(base_type const & in, indicator ind, long & out) + 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(in); + out = static_cast(in); } - static void to_base(long const & in, base_type & out, indicator & ind) + static void to_base(long long const & in, base_type & out, indicator & ind) { out = static_cast(in); ind = i_ok; @@ -39,27 +40,27 @@ struct type_conversion }; template <> -struct type_conversion +struct type_conversion { - typedef uint32_t base_type; + typedef uint64_t base_type; - static void from_base(base_type const & in, indicator ind, unsigned long & out) + 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(in); + out = static_cast(in); } - static void to_base(unsigned long const & in, base_type & out, indicator & ind) + static void to_base(unsigned long long const & in, base_type & out, indicator & ind) { out = static_cast(in); ind = i_ok; } }; -#elif defined(__APPLE__) +#elif defined(SOCI_LONG_IS_64_BIT) template <> struct type_conversion { @@ -103,23 +104,23 @@ struct type_conversion ind = i_ok; } }; -#elif defined(__LP64__) || (__WORDSIZE == 64) +#else template <> -struct type_conversion +struct type_conversion { - typedef int64_t base_type; + typedef int32_t base_type; - static void from_base(base_type const & in, indicator ind, long long & out) + 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(in); + out = static_cast(in); } - static void to_base(long long const & in, base_type & out, indicator & ind) + static void to_base(long const & in, base_type & out, indicator & ind) { out = static_cast(in); ind = i_ok; @@ -127,28 +128,26 @@ struct type_conversion }; template <> -struct type_conversion +struct type_conversion { - typedef uint64_t base_type; + typedef uint32_t base_type; - static void from_base(base_type const & in, indicator ind, unsigned long long & out) + 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(in); + out = static_cast(in); } - static void to_base(unsigned long long const & in, base_type & out, indicator & ind) + static void to_base(unsigned long const & in, base_type & out, indicator & ind) { out = static_cast(in); ind = i_ok; } }; -#else -#error "Unhandled type architecture" #endif } // namespace soci diff --git a/include/soci/soci-platform.h b/include/soci/soci-platform.h index 3f94cb57b..bb2b8eeff 100644 --- a/include/soci/soci-platform.h +++ b/include/soci/soci-platform.h @@ -175,4 +175,23 @@ private: \ #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 diff --git a/include/soci/soci-types.h b/include/soci/soci-types.h new file mode 100644 index 000000000..be94bc3c8 --- /dev/null +++ b/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 From e8e4fc9b664a0e1c025b20edc0c621cdc2925f97 Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Wed, 4 Jan 2023 21:07:51 +0100 Subject: [PATCH 32/46] Fix MSSQL ODBC unit tests --- include/soci/odbc/soci-odbc.h | 21 +++++++++++++++++++++ src/backends/odbc/standard-use-type.cpp | 12 ++++++------ src/backends/odbc/vector-use-type.cpp | 14 +++++++------- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/include/soci/odbc/soci-odbc.h b/include/soci/odbc/soci-odbc.h index 4c32ef211..c467c01d9 100644 --- a/include/soci/odbc/soci-odbc.h +++ b/include/soci/odbc/soci-odbc.h @@ -78,6 +78,8 @@ class odbc_standard_type_backend_base 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: @@ -545,6 +547,25 @@ inline void odbc_standard_type_backend_base::set_sqllen_from_value(SQLLEN &targe } } +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()) diff --git a/src/backends/odbc/standard-use-type.cpp b/src/backends/odbc/standard-use-type.cpp index fc7662e02..12c573cd7 100644 --- a/src/backends/odbc/standard-use-type.cpp +++ b/src/backends/odbc/standard-use-type.cpp @@ -25,12 +25,12 @@ void* odbc_standard_use_type_backend::prepare_for_bind( { // simple cases case x_int8: - sqlType = SQL_TINYINT; + sqlType = supports_negative_tinyint() ? SQL_TINYINT : SQL_SMALLINT; cType = SQL_C_STINYINT; size = sizeof(int8_t); break; case x_uint8: - sqlType = SQL_TINYINT; + sqlType = can_convert_to_unsigned_sql_type() ? SQL_TINYINT : SQL_SMALLINT; cType = SQL_C_UTINYINT; size = sizeof(uint8_t); break; @@ -40,7 +40,7 @@ void* odbc_standard_use_type_backend::prepare_for_bind( size = sizeof(int16_t); break; case x_uint16: - sqlType = SQL_SMALLINT; + sqlType = can_convert_to_unsigned_sql_type() ? SQL_SMALLINT : SQL_INTEGER; cType = SQL_C_USHORT; size = sizeof(uint16_t); break; @@ -50,7 +50,7 @@ void* odbc_standard_use_type_backend::prepare_for_bind( size = sizeof(int32_t); break; case x_uint32: - sqlType = SQL_INTEGER; + sqlType = can_convert_to_unsigned_sql_type() ? SQL_INTEGER : SQL_BIGINT; cType = SQL_C_ULONG; size = sizeof(uint32_t); break; @@ -73,7 +73,7 @@ void* odbc_standard_use_type_backend::prepare_for_bind( } break; case x_uint64: - if (use_string_for_bigint()) + if (use_string_for_bigint() || !can_convert_to_unsigned_sql_type()) { sqlType = SQL_NUMERIC; cType = SQL_C_CHAR; @@ -83,7 +83,7 @@ void* odbc_standard_use_type_backend::prepare_for_bind( static_cast(exchange_type_cast(data_))); indHolder_ = SQL_NTS; } - else // Normal case, use ODBC support. + else { sqlType = SQL_BIGINT; cType = SQL_C_UBIGINT; diff --git a/src/backends/odbc/vector-use-type.cpp b/src/backends/odbc/vector-use-type.cpp index dad2233c8..b6dfa6250 100644 --- a/src/backends/odbc/vector-use-type.cpp +++ b/src/backends/odbc/vector-use-type.cpp @@ -45,7 +45,7 @@ void* odbc_vector_use_type_backend::prepare_for_bind(SQLUINTEGER &size, { // simple cases case x_int8: { - sqlType = SQL_TINYINT; + sqlType = supports_negative_tinyint() ? SQL_TINYINT : SQL_SMALLINT; cType = SQL_C_STINYINT; size = sizeof(int8_t); std::vector *vp = static_cast *>(data_); @@ -56,7 +56,7 @@ void* odbc_vector_use_type_backend::prepare_for_bind(SQLUINTEGER &size, break; case x_uint8: { - sqlType = SQL_TINYINT; + sqlType = can_convert_to_unsigned_sql_type() ? SQL_TINYINT : SQL_SMALLINT; cType = SQL_C_UTINYINT; size = sizeof(uint8_t); std::vector *vp = static_cast *>(data_); @@ -78,7 +78,7 @@ void* odbc_vector_use_type_backend::prepare_for_bind(SQLUINTEGER &size, break; case x_uint16: { - sqlType = SQL_SMALLINT; + sqlType = can_convert_to_unsigned_sql_type() ? SQL_SMALLINT : SQL_INTEGER; cType = SQL_C_USHORT; size = sizeof(uint16_t); std::vector *vp = static_cast *>(data_); @@ -101,7 +101,7 @@ void* odbc_vector_use_type_backend::prepare_for_bind(SQLUINTEGER &size, break; case x_uint32: { - sqlType = SQL_INTEGER; + sqlType = can_convert_to_unsigned_sql_type() ? SQL_INTEGER : SQL_BIGINT; cType = SQL_C_ULONG; size = sizeof(SQLINTEGER); std::vector *vp = static_cast *>(data_); @@ -143,7 +143,7 @@ void* odbc_vector_use_type_backend::prepare_for_bind(SQLUINTEGER &size, std::size_t const vsize = v.size(); prepare_indicators(vsize); - if (use_string_for_bigint()) + if (use_string_for_bigint() || !can_convert_to_unsigned_sql_type()) { sqlType = SQL_NUMERIC; cType = SQL_C_CHAR; @@ -151,7 +151,7 @@ void* odbc_vector_use_type_backend::prepare_for_bind(SQLUINTEGER &size, buf_ = new char[size * vsize]; data = buf_; } - else // Normal case, use ODBC support. + else // Normal case, use ODBC support { sqlType = SQL_BIGINT; cType = SQL_C_UBIGINT; @@ -397,7 +397,7 @@ void odbc_vector_use_type_backend::pre_use(indicator const *ind) break; case x_uint64: - if (use_string_for_bigint()) + if (use_string_for_bigint() || !can_convert_to_unsigned_sql_type()) { std::vector *vp = static_cast *>(data_); From 4de379f17832c4b0b17b8ea77fd03f6a87c3420c Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Sun, 8 Jan 2023 12:47:09 +0100 Subject: [PATCH 33/46] Fix Postgres unit test --- tests/postgresql/test-postgresql.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/postgresql/test-postgresql.cpp b/tests/postgresql/test-postgresql.cpp index 2dbf28b5d..a31557924 100644 --- a/tests/postgresql/test-postgresql.cpp +++ b/tests/postgresql/test-postgresql.cpp @@ -1163,7 +1163,7 @@ TEST_CASE("test_enum_with_explicit_custom_type_string_rowset", "[postgresql][bin statement s2 = (sql.prepare << "SELECT Type FROM soci_test;"); s1.execute(false); - + soci::row result; s2.define_and_bind(); s2.exchange_for_rowset(soci::into(result)); @@ -1204,7 +1204,7 @@ struct test_enum_with_explicit_custom_type_int_rowset : table_creator_base try { - sql << "CREATE TABLE soci_test( Type smallint)"; + sql << "CREATE TABLE soci_test( Type integer)"; ; } catch (...) From 1c3e06930d1979b82fe7c97ea11cbd4469177a12 Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Sun, 15 Jan 2023 19:14:18 +0100 Subject: [PATCH 34/46] Fix MySQL ODBC unit tests --- tests/common-tests.h | 21 +++++++++++++++++++-- tests/odbc/test-odbc-mysql.cpp | 19 ++++++++++++++++++- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/tests/common-tests.h b/tests/common-tests.h index 1f8cfcc5a..305c3971a 100644 --- a/tests/common-tests.h +++ b/tests/common-tests.h @@ -471,6 +471,9 @@ class test_context_base // values might be stored as overflown and therefore negative integer. virtual bool has_uint64_storage_bug() const { return false; } + // Override this if the backend truncates integer values bigger than INT64_MAX. + virtual bool truncates_uint64_to_int64() const { return false; } + // Override this to call commit() if it's necessary for the DDL statements // to be taken into account (currently this is only the case for Firebird). virtual void on_after_ddl(session&) const { } @@ -1796,7 +1799,14 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") ui2 = 0; sql << "select ul from soci_test", into(ui2); - CHECK(ui2 == (std::numeric_limits::max)()); + if (tc_.truncates_uint64_to_int64()) + { + CHECK(ui2 == static_cast((std::numeric_limits::max)())); + } + else + { + CHECK(ui2 == (std::numeric_limits::max)()); + } } SECTION("double") @@ -2427,7 +2437,14 @@ TEST_CASE_METHOD(common_tests, "Use vector", "[core][use][vector]") CHECK(v2[2] == 1); CHECK(v2[3] == 123); CHECK(v2[4] == 1000); - CHECK(v2[5] == (std::numeric_limits::max)()); + if (tc_.truncates_uint64_to_int64()) + { + CHECK(v2[5] == static_cast((std::numeric_limits::max)())); + } + else + { + CHECK(v2[5] == (std::numeric_limits::max)()); + } } } diff --git a/tests/odbc/test-odbc-mysql.cpp b/tests/odbc/test-odbc-mysql.cpp index 9ea70adf6..5b14e7ea4 100644 --- a/tests/odbc/test-odbc-mysql.cpp +++ b/tests/odbc/test-odbc-mysql.cpp @@ -16,6 +16,23 @@ std::string connectString; backend_factory const &backEnd = *soci::factory_odbc(); +class test_context_odbc : public test_context +{ +public: + using test_context::test_context; + + bool truncates_uint64_to_int64() const override + { + // The ODBC driver of MySQL truncates values bigger then INT64_MAX. + // There are open bugs related to this issue: + // - https://bugs.mysql.com/bug.php?id=95978 + // - https://bugs.mysql.com/bug.php?id=61114 + // Driver version 8.0.31 seems to have fixed this (https://github.com/mysql/mysql-connector-odbc/commit/e78da1344247752f76a082de51cfd36d5d2dd98f), + // but we use an older version in the AppVeyor builds. + return true; + } +}; + int main(int argc, char** argv) { #ifdef _MSC_VER @@ -43,7 +60,7 @@ int main(int argc, char** argv) connectString = "FILEDSN=./test-mysql.dsn"; } - test_context tc(backEnd, connectString); + test_context_odbc tc(backEnd, connectString); return Catch::Session().run(argc, argv); } From ff7e29cca132a4fcd2e53b380cdd0dc2ab5b4968 Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Sun, 13 Aug 2023 17:12:17 +0200 Subject: [PATCH 35/46] Handle potential overflow in mysql into-conversion --- src/backends/mysql/standard-into-type.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/backends/mysql/standard-into-type.cpp b/src/backends/mysql/standard-into-type.cpp index 06f98e694..edb68684f 100644 --- a/src/backends/mysql/standard-into-type.cpp +++ b/src/backends/mysql/standard-into-type.cpp @@ -6,6 +6,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // +#include "soci-cstrtoi.h" #define SOCI_MYSQL_SOURCE #include "soci/mysql/soci-mysql.h" #include "soci/soci-platform.h" @@ -94,6 +95,11 @@ void mysql_standard_into_type_backend::post_fetch( { int32_t tmp = 0; parse_num(buf, tmp); + if (tmp < (std::numeric_limits::min)() || + tmp > (std::numeric_limits::max)()) + { + throw soci_error("Cannot convert data."); + } exchange_type_cast(data_) = static_cast(tmp); } break; @@ -101,6 +107,11 @@ void mysql_standard_into_type_backend::post_fetch( { uint32_t tmp = 0; parse_num(buf, tmp); + if (tmp < (std::numeric_limits::min)() || + tmp > (std::numeric_limits::max)()) + { + throw soci_error("Cannot convert data."); + } exchange_type_cast(data_) = static_cast(tmp); } break; From 826fa7753a4a30c22e026847dec785aa133f0a3b Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Fri, 11 Aug 2023 17:26:22 +0200 Subject: [PATCH 36/46] Expose new db_type for dynamic type mapping --- include/soci/column-info.h | 35 ++- include/soci/db2/soci-db2.h | 2 +- include/soci/empty/soci-empty.h | 2 +- include/soci/firebird/soci-firebird.h | 1 + include/soci/mysql/soci-mysql.h | 1 + include/soci/odbc/soci-odbc.h | 1 + include/soci/once-temp-type.h | 3 + include/soci/oracle/soci-oracle.h | 105 +++++++- include/soci/postgresql/soci-postgresql.h | 1 + include/soci/row.h | 6 + include/soci/soci-backend.h | 155 +++++++++-- include/soci/sqlite3/soci-sqlite3.h | 46 +++- include/soci/statement.h | 2 +- src/backends/db2/statement.cpp | 17 +- src/backends/empty/statement.cpp | 3 +- src/backends/firebird/statement.cpp | 34 ++- src/backends/mysql/statement.cpp | 41 ++- src/backends/odbc/statement.cpp | 16 +- src/backends/oracle/statement.cpp | 13 +- src/backends/postgresql/statement.cpp | 18 +- src/backends/sqlite3/standard-use-type.cpp | 33 ++- src/backends/sqlite3/statement.cpp | 160 +++++------ src/backends/sqlite3/vector-into-type.cpp | 148 +++++----- src/backends/sqlite3/vector-use-type.cpp | 29 +- src/core/once-temp-type.cpp | 18 ++ src/core/soci-simple.cpp | 298 ++++++++++----------- src/core/statement.cpp | 80 +++--- tests/common-tests.h | 51 ++++ tests/firebird/test-firebird.cpp | 12 + tests/mysql/test-mysql.cpp | 27 +- tests/postgresql/test-postgresql.cpp | 10 + 31 files changed, 910 insertions(+), 458 deletions(-) diff --git a/include/soci/column-info.h b/include/soci/column-info.h index 5cc7ed22c..21a04f013 100644 --- a/include/soci/column-info.h +++ b/include/soci/column-info.h @@ -20,7 +20,9 @@ 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; @@ -35,37 +37,36 @@ struct type_conversion static std::size_t get_numeric_value(const values & v, const std::string & field_name) { - data_type dt = v.get_properties(field_name).get_data_type(); + db_type dt = v.get_properties(field_name).get_db_type(); switch (dt) { - case dt_double: + case db_double: return static_cast( v.get(field_name, 0.0)); - case dt_int8: + case db_int8: return static_cast( v.get(field_name, 0)); - case dt_uint8: + case db_uint8: return static_cast( v.get(field_name, 0)); - case dt_int16: + case db_int16: return static_cast( v.get(field_name, 0)); - case dt_uint16: + case db_uint16: return static_cast( v.get(field_name, 0)); - case dt_int32: + case db_int32: return static_cast( v.get(field_name, 0)); - case dt_uint32: + case db_uint32: return static_cast( v.get(field_name, 0)); - case dt_int64: + case db_int64: return static_cast( v.get(field_name, 0ll)); - case dt_uint64: + case db_uint64: return static_cast( v.get(field_name, 0ull)); - break; default: return 0u; } @@ -86,10 +87,12 @@ struct type_conversion 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_int32; + ci.type = dt_integer; + ci.dataType = db_int32; } else if (type_name.find("number") != std::string::npos || type_name.find("NUMBER") != std::string::npos || @@ -99,10 +102,12 @@ struct type_conversion if (ci.scale != 0) { ci.type = dt_double; + ci.dataType = db_double; } else { - ci.type = dt_int32; + ci.type = dt_integer; + ci.dataType = db_int32; } } else if (type_name.find("time") != std::string::npos || @@ -111,6 +116,7 @@ struct type_conversion 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 || @@ -118,16 +124,19 @@ struct type_conversion 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("IS_NULLABLE"); diff --git a/include/soci/db2/soci-db2.h b/include/soci/db2/soci-db2.h index fcd326d59..5ede930b0 100644 --- a/include/soci/db2/soci-db2.h +++ b/include/soci/db2/soci-db2.h @@ -197,7 +197,7 @@ struct SOCI_DB2_DECL db2_statement_backend : details::statement_backend std::string rewrite_for_procedure_call(std::string const& query) override; int prepare_for_describe() override; - void describe_column(int colNum, data_type& dtype, std::string& columnName) override; + void describe_column(int colNum, data_type& dtype, db_type& dbtype, std::string& columnName) override; size_t column_size(int col); db2_standard_into_type_backend* make_into_type_backend() override; diff --git a/include/soci/empty/soci-empty.h b/include/soci/empty/soci-empty.h index eb58e8524..c7c62ec3f 100644 --- a/include/soci/empty/soci-empty.h +++ b/include/soci/empty/soci-empty.h @@ -114,7 +114,7 @@ struct SOCI_EMPTY_DECL empty_statement_backend : details::statement_backend std::string rewrite_for_procedure_call(std::string const& query) override; int prepare_for_describe() override; - void describe_column(int colNum, data_type& dtype, std::string& columnName) override; + void describe_column(int colNum, data_type& dtype, 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; diff --git a/include/soci/firebird/soci-firebird.h b/include/soci/firebird/soci-firebird.h index 61bc76716..fef98de02 100644 --- a/include/soci/firebird/soci-firebird.h +++ b/include/soci/firebird/soci-firebird.h @@ -202,6 +202,7 @@ struct firebird_statement_backend : details::statement_backend int prepare_for_describe() override; void describe_column(int colNum, data_type &dtype, + db_type &dbtype, std::string &columnName) override; firebird_standard_into_type_backend * make_into_type_backend() override; diff --git a/include/soci/mysql/soci-mysql.h b/include/soci/mysql/soci-mysql.h index 456b0239e..daa2f44bc 100644 --- a/include/soci/mysql/soci-mysql.h +++ b/include/soci/mysql/soci-mysql.h @@ -182,6 +182,7 @@ struct mysql_statement_backend : details::statement_backend int prepare_for_describe() override; void describe_column(int colNum, data_type &dtype, + db_type &dbtype, std::string &columnName) override; mysql_standard_into_type_backend * make_into_type_backend() override; diff --git a/include/soci/odbc/soci-odbc.h b/include/soci/odbc/soci-odbc.h index c467c01d9..833d33711 100644 --- a/include/soci/odbc/soci-odbc.h +++ b/include/soci/odbc/soci-odbc.h @@ -254,6 +254,7 @@ struct odbc_statement_backend : details::statement_backend int prepare_for_describe() override; void describe_column(int colNum, data_type &dtype, + db_type &dbtype, std::string &columnName) override; // helper for defining into vector diff --git a/include/soci/once-temp-type.h b/include/soci/once-temp-type.h index a6be0942a..b860d35e8 100644 --- a/include/soci/once-temp-type.h +++ b/include/soci/once-temp-type.h @@ -133,8 +133,11 @@ class SOCI_DECL ddl_type int precision, int scale); void drop_column(const std::string & tableName, const std::string & columnName); + // DEPRECATED. USE column(std::string, db_type, int, int) INSTEAD. ddl_type & column(const std::string & columnName, data_type dt, int precision = 0, int scale = 0); + 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, diff --git a/include/soci/oracle/soci-oracle.h b/include/soci/oracle/soci-oracle.h index 255692a6b..6224caf5c 100644 --- a/include/soci/oracle/soci-oracle.h +++ b/include/soci/oracle/soci-oracle.h @@ -230,6 +230,7 @@ struct oracle_statement_backend : details::statement_backend int prepare_for_describe() override; void describe_column(int colNum, data_type &dtype, + db_type &dbtype, std::string &columnName) override; // helper for defining into vector @@ -330,6 +331,78 @@ struct oracle_session_backend : details::session_backend } std::string create_column_type(data_type dt, + int precision, int scale) override + { + // Oracle-specific SQL syntax: + + std::string res; + switch (dt) + { + case dt_string: + { + std::ostringstream oss; + + if (precision == 0) + { + oss << "clob"; + } + else + { + oss << "varchar(" << precision << ")"; + } + + res += oss.str(); + } + break; + + case dt_date: + res += "timestamp"; + break; + + case dt_double: + { + std::ostringstream oss; + if (precision == 0) + { + oss << "number"; + } + else + { + oss << "number(" << precision << ", " << scale << ")"; + } + + res += oss.str(); + } + break; + + case dt_integer: + res += "integer"; + break; + + case dt_long_long: + res += "number"; + break; + + case dt_unsigned_long_long: + res += "number"; + break; + + case dt_blob: + res += "blob"; + break; + + case dt_xml: + res += "xmltype"; + break; + + default: + throw soci_error("this data_type is not supported in create_column"); + } + + return res; + } + + std::string create_column_type(db_type dt, int precision, int scale) override { // Oracle-specific SQL syntax: @@ -337,7 +410,7 @@ struct oracle_session_backend : details::session_backend std::string res; switch (dt) { - case dt_string: + case db_string: { std::ostringstream oss; @@ -354,11 +427,11 @@ struct oracle_session_backend : details::session_backend } break; - case dt_date: + case db_date: res += "timestamp"; break; - case dt_double: + case db_double: { std::ostringstream oss; if (precision == 0) @@ -374,27 +447,27 @@ struct oracle_session_backend : details::session_backend } break; - case dt_int16: + case db_int16: res += "smallint"; break; - case dt_int32: + case db_int32: res += "integer"; break; - case dt_int64: + case db_int64: res += "number"; break; - case dt_uint64: + case db_uint64: res += "number"; break; - case dt_blob: + case db_blob: res += "blob"; break; - case dt_xml: + case db_xml: res += "xmltype"; break; @@ -407,6 +480,13 @@ struct oracle_session_backend : details::session_backend std::string add_column(const std::string & tableName, const std::string & columnName, data_type dt, int precision, int scale) override + { + return "alter table " + tableName + " add " + + columnName + " " + create_column_type(dt, precision, scale); + } + 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); @@ -414,6 +494,13 @@ struct oracle_session_backend : details::session_backend std::string alter_column(const std::string & tableName, const std::string & columnName, data_type dt, int precision, int scale) override + { + return "alter table " + tableName + " modify " + + 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); diff --git a/include/soci/postgresql/soci-postgresql.h b/include/soci/postgresql/soci-postgresql.h index f518d2e9d..594d41034 100644 --- a/include/soci/postgresql/soci-postgresql.h +++ b/include/soci/postgresql/soci-postgresql.h @@ -271,6 +271,7 @@ struct postgresql_statement_backend : details::statement_backend int prepare_for_describe() override; void describe_column(int colNum, data_type & dtype, + db_type & dbtype, std::string & columnName) override; postgresql_standard_into_type_backend * make_into_type_backend() override; diff --git a/include/soci/row.h b/include/soci/row.h index 8cd816dc4..3279dae25 100644 --- a/include/soci/row.h +++ b/include/soci/row.h @@ -27,14 +27,20 @@ class SOCI_DECL column_properties 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 diff --git a/include/soci/soci-backend.h b/include/soci/soci-backend.h index 5d3d94b0f..494aff669 100644 --- a/include/soci/soci-backend.h +++ b/include/soci/soci-backend.h @@ -19,27 +19,38 @@ namespace soci { +// DEPRECATED. USE db_type INSTEAD. // data types, as seen by the user enum data_type { dt_string, - dt_int8, - dt_uint8, - dt_int16, - dt_uint16, - dt_int32, - dt_integer = dt_int32, - dt_uint32, - dt_int64, - dt_long_long = dt_int64, - dt_uint64, - dt_unsigned_long_long = dt_uint64, + dt_integer, + dt_long_long, + dt_unsigned_long_long, dt_double, dt_date, dt_blob, dt_xml }; +// 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 +}; + // the enum type for indicator variables enum indicator { i_ok, i_null, i_truncated }; @@ -220,6 +231,7 @@ class statement_backend virtual int prepare_for_describe() = 0; virtual void describe_column(int colNum, data_type& dtype, + db_type& dbtype, std::string& column_name) = 0; virtual standard_into_type_backend* make_into_type_backend() = 0; @@ -335,7 +347,77 @@ class session_backend { return "truncate table " + tableName; } + // DEPRECATED. USE create_column_type(db_type, int, int) INSTEAD. virtual std::string create_column_type(data_type dt, + int precision, int scale) + { + // PostgreSQL was selected as a baseline for the syntax: + + std::string res; + switch (dt) + { + case dt_string: + { + std::ostringstream oss; + + if (precision == 0) + { + oss << "text"; + } + else + { + oss << "varchar(" << precision << ")"; + } + + res += oss.str(); + } + break; + + case dt_date: + res += "timestamp"; + break; + + case dt_double: + { + std::ostringstream oss; + if (precision == 0) + { + oss << "numeric"; + } + else + { + oss << "numeric(" << precision << ", " << scale << ")"; + } + + res += oss.str(); + } + break; + + case dt_integer: + res += "integer"; + break; + + case dt_long_long: + res += "bigint"; + break; + + case dt_unsigned_long_long: + + case dt_blob: + res += "oid"; + break; + + case dt_xml: + res += "xml"; + break; + + default: + throw soci_error("this data_type is not supported in create_column"); + } + + return res; + } + virtual std::string create_column_type(db_type dt, int precision, int scale) { // PostgreSQL was selected as a baseline for the syntax: @@ -343,7 +425,7 @@ class session_backend std::string res; switch (dt) { - case dt_string: + case db_string: { std::ostringstream oss; @@ -360,11 +442,11 @@ class session_backend } break; - case dt_date: + case db_date: res += "timestamp"; break; - case dt_double: + case db_double: { std::ostringstream oss; if (precision == 0) @@ -380,35 +462,36 @@ class session_backend } break; - case dt_int16: - case dt_uint16: + case db_int16: + case db_uint16: res += "smallint"; break; - case dt_int32: - case dt_uint32: + case db_int32: + case db_uint32: res += "integer"; break; - case dt_int64: - case dt_uint64: + case db_int64: + case db_uint64: res += "bigint"; break; - case dt_blob: + case db_blob: res += "oid"; break; - case dt_xml: + case db_xml: res += "xml"; break; default: - throw soci_error("this data_type is not supported in create_column"); + throw soci_error("this db_type is not supported in create_column"); } return res; } + // DEPRECATED. USE add_column(std::string, std::string, db_type, int, int) INSTEAD. virtual std::string add_column(const std::string & tableName, const std::string & columnName, data_type dt, int precision, int scale) @@ -416,13 +499,31 @@ class session_backend return "alter table " + tableName + " add column " + columnName + " " + create_column_type(dt, precision, scale); } + 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); + } + // DEPRECATED. USE alter_column(std::string, std::string, db_type, int, int) INSTEAD. virtual std::string alter_column(const std::string & tableName, - const std::string & columnName, data_type dt, - int precision, int scale) + const std::string & columnName, data_type dt, + int precision, int scale) + { + return "alter table " + tableName + " alter column " + + columnName + " type " + + 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); + columnName + " type " + + create_column_type(dt, precision, scale); } virtual std::string drop_column(const std::string & tableName, const std::string & columnName) diff --git a/include/soci/sqlite3/soci-sqlite3.h b/include/soci/sqlite3/soci-sqlite3.h index f62282cce..28ae3b634 100644 --- a/include/soci/sqlite3/soci-sqlite3.h +++ b/include/soci/sqlite3/soci-sqlite3.h @@ -170,7 +170,9 @@ struct sqlite3_column_buffer struct sqlite3_column { bool isNull_; + // DEPRECATED. USE dataType_ INSTEAD. data_type type_; + db_type dataType_; union { @@ -193,7 +195,9 @@ typedef std::vector 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_list; @@ -221,6 +225,7 @@ struct sqlite3_statement_backend : details::statement_backend int prepare_for_describe() override; void describe_column(int colNum, data_type &dtype, + db_type &dbtype, std::string &columnName) override; sqlite3_standard_into_type_backend * make_into_type_backend() override; @@ -315,7 +320,7 @@ struct sqlite3_session_backend : details::session_backend " from sqlite_master where type = 'table'"; } std::string create_column_type(data_type dt, - int , int ) override + int , int ) override { switch (dt) { @@ -325,22 +330,43 @@ struct sqlite3_session_backend : details::session_backend case dt_double: return "real"; case dt_date: - case dt_int8: - case dt_uint8: - case dt_int16: - case dt_uint16: - case dt_int32: - case dt_uint32: - case dt_int64: - case dt_uint64: + case dt_integer: + case dt_long_long: + case dt_unsigned_long_long: return "integer"; case dt_blob: return "blob"; default: throw soci_error("this data_type is not supported in create_column"); } - } + 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: + case db_int8: + case db_uint8: + case db_int16: + case db_uint16: + case db_int32: + case db_uint32: + case db_int64: + case db_uint64: + return "integer"; + case db_blob: + return "blob"; + default: + throw soci_error("this data_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 diff --git a/include/soci/statement.h b/include/soci/statement.h index b356762e0..a1397d106 100644 --- a/include/soci/statement.h +++ b/include/soci/statement.h @@ -144,7 +144,7 @@ class SOCI_DECL statement_impl exchange_for_row(into(*t, *ind)); } - template + template void bind_into(); bool alreadyDescribed_; diff --git a/src/backends/db2/statement.cpp b/src/backends/db2/statement.cpp index f9c0b02b0..1c154fb46 100644 --- a/src/backends/db2/statement.cpp +++ b/src/backends/db2/statement.cpp @@ -225,7 +225,7 @@ int db2_statement_backend::prepare_for_describe() } void db2_statement_backend::describe_column(int colNum, - data_type & type, std::string & columnName ) + data_type & type, db_type & dbtype, std::string & columnName ) { SQLCHAR colNameBuffer[2048]; SQLSMALLINT colNameBufferOverflow; @@ -253,6 +253,7 @@ SQLCHAR colNameBuffer[2048]; case SQL_TYPE_TIME: case SQL_TYPE_TIMESTAMP: type = dt_date; + dbtype = db_date; break; case SQL_DOUBLE: case SQL_DECIMAL: @@ -260,24 +261,30 @@ SQLCHAR colNameBuffer[2048]; case SQL_FLOAT: case SQL_NUMERIC: type = dt_double; + dbtype = db_double; break; case SQL_TINYINT: - type = dt_int8; + type = dt_integer; + dbtype = db_int8; break; case SQL_SMALLINT: - type = dt_int16; + type = dt_integer; + dbtype = db_int16; break; case SQL_INTEGER: - type = dt_int32; + type = dt_integer; + dbtype = db_int32; break; case SQL_BIGINT: - type = dt_int64; + type = dt_long_long; + dbtype = db_int64; break; case SQL_CHAR: case SQL_VARCHAR: case SQL_LONGVARCHAR: default: type = dt_string; + dbtype = db_string; break; } } diff --git a/src/backends/empty/statement.cpp b/src/backends/empty/statement.cpp index 87f9fda9f..045bee5cd 100644 --- a/src/backends/empty/statement.cpp +++ b/src/backends/empty/statement.cpp @@ -82,7 +82,8 @@ int empty_statement_backend::prepare_for_describe() } void empty_statement_backend::describe_column(int /* colNum */, - data_type & /* type */, std::string & /* columnName */) + data_type & /* type */, db_type & /* dbtype */, + std::string & /* columnName */) { // ... } diff --git a/src/backends/firebird/statement.cpp b/src/backends/firebird/statement.cpp index fc5e59f4c..0249543c5 100644 --- a/src/backends/firebird/statement.cpp +++ b/src/backends/firebird/statement.cpp @@ -658,7 +658,9 @@ int firebird_statement_backend::prepare_for_describe() } void firebird_statement_backend::describe_column(int colNum, - data_type & type, std::string & columnName) + data_type & type, + db_type & dbtype, + std::string & columnName) { XSQLVAR * var = sqldap_->sqlvar+(colNum-1); @@ -669,53 +671,77 @@ void firebird_statement_backend::describe_column(int colNum, case SQL_TEXT: case SQL_VARYING: type = dt_string; + dbtype = db_string; break; case SQL_TYPE_DATE: case SQL_TYPE_TIME: case SQL_TIMESTAMP: type = dt_date; + dbtype = db_date; break; case SQL_FLOAT: case SQL_DOUBLE: type = dt_double; + dbtype = db_double; break; case SQL_SHORT: if (var->sqlscale < 0) { if (session_.get_option_decimals_as_strings()) + { type = dt_string; + dbtype = db_string; + } else + { type = dt_double; + dbtype = db_double; + } } else { - type = dt_int16; + type = dt_integer; + dbtype = db_int16; } break; case SQL_LONG: if (var->sqlscale < 0) { if (session_.get_option_decimals_as_strings()) + { type = dt_string; + dbtype = db_string; + } else + { type = dt_double; + dbtype = db_double; + } } else { - type = dt_int32; + type = dt_integer; + dbtype = db_int32; } break; case SQL_INT64: if (var->sqlscale < 0) { if (session_.get_option_decimals_as_strings()) + { type = dt_string; + dbtype = db_string; + } else + { type = dt_double; + dbtype = db_double; + } } else { - type = dt_int64; + type = dt_long_long; + dbtype = db_int64; } break; /* case SQL_BLOB: diff --git a/src/backends/mysql/statement.cpp b/src/backends/mysql/statement.cpp index 3d83201b3..cd901602d 100644 --- a/src/backends/mysql/statement.cpp +++ b/src/backends/mysql/statement.cpp @@ -402,31 +402,47 @@ int mysql_statement_backend::prepare_for_describe() } void mysql_statement_backend::describe_column(int colNum, - data_type & type, std::string & columnName) + data_type & type, db_type & dbtype, std::string & columnName) { int pos = colNum - 1; MYSQL_FIELD *field = mysql_fetch_field_direct(result_, pos); switch (field->type) { case FIELD_TYPE_CHAR: //MYSQL_TYPE_TINY: - type = field->flags & UNSIGNED_FLAG ? dt_uint8 : - dt_int8; + type = dt_integer; + dbtype = field->flags & UNSIGNED_FLAG ? db_uint8 : db_int8; break; case FIELD_TYPE_SHORT: //MYSQL_TYPE_SHORT: - type = field->flags & UNSIGNED_FLAG ? dt_uint16 : - dt_int16; + type = dt_integer; + dbtype = field->flags & UNSIGNED_FLAG ? db_uint16 : db_int16; break; case FIELD_TYPE_INT24: //MYSQL_TYPE_INT24: - type = field->flags & UNSIGNED_FLAG ? dt_uint32 - : dt_int32; + type = dt_integer; + dbtype = field->flags & UNSIGNED_FLAG ? db_uint32 : db_int32; break; case FIELD_TYPE_LONG: //MYSQL_TYPE_LONG: - type = field->flags & UNSIGNED_FLAG ? dt_uint32 - : dt_int32; + if (field->flags & UNSIGNED_FLAG) + { + type = dt_long_long; + dbtype = db_uint32; + } + else + { + type = dt_integer; + dbtype = db_int32; + } break; case FIELD_TYPE_LONGLONG: //MYSQL_TYPE_LONGLONG: - type = field->flags & UNSIGNED_FLAG ? dt_uint64 : - dt_int64; + if (field->flags & UNSIGNED_FLAG) + { + type = dt_unsigned_long_long; + dbtype = db_uint64; + } + else + { + type = dt_long_long; + dbtype = db_int64; + } break; case FIELD_TYPE_FLOAT: //MYSQL_TYPE_FLOAT: case FIELD_TYPE_DOUBLE: //MYSQL_TYPE_DOUBLE: @@ -437,6 +453,7 @@ void mysql_statement_backend::describe_column(int colNum, // the client is using. case 246: //MYSQL_TYPE_NEWDECIMAL: type = dt_double; + dbtype = db_double; break; case FIELD_TYPE_TIMESTAMP: //MYSQL_TYPE_TIMESTAMP: case FIELD_TYPE_DATE: //MYSQL_TYPE_DATE: @@ -445,6 +462,7 @@ void mysql_statement_backend::describe_column(int colNum, case FIELD_TYPE_YEAR: //MYSQL_TYPE_YEAR: case FIELD_TYPE_NEWDATE: //MYSQL_TYPE_NEWDATE: type = dt_date; + dbtype = db_date; break; // case MYSQL_TYPE_VARCHAR: case 245: //MYSQL_TYPE_JSON: @@ -455,6 +473,7 @@ void mysql_statement_backend::describe_column(int colNum, case FIELD_TYPE_MEDIUM_BLOB: case FIELD_TYPE_LONG_BLOB: type = dt_string; + dbtype = db_string; break; default: //std::cerr << "field->type: " << field->type << std::endl; diff --git a/src/backends/odbc/statement.cpp b/src/backends/odbc/statement.cpp index bcacf6604..816953f1a 100644 --- a/src/backends/odbc/statement.cpp +++ b/src/backends/odbc/statement.cpp @@ -328,6 +328,7 @@ int odbc_statement_backend::prepare_for_describe() } void odbc_statement_backend::describe_column(int colNum, data_type & type, + db_type & dbtype, std::string & columnName) { SQLCHAR colNameBuffer[2048]; @@ -369,6 +370,7 @@ void odbc_statement_backend::describe_column(int colNum, data_type & type, case SQL_TYPE_TIME: case SQL_TYPE_TIMESTAMP: type = dt_date; + dbtype = db_date; break; case SQL_DOUBLE: case SQL_DECIMAL: @@ -376,24 +378,30 @@ void odbc_statement_backend::describe_column(int colNum, data_type & type, case SQL_FLOAT: case SQL_NUMERIC: type = dt_double; + dbtype = db_double; break; case SQL_TINYINT: - type = is_unsigned == SQL_TRUE ? dt_uint8 : dt_int8; + type = dt_integer; + dbtype = is_unsigned == SQL_TRUE ? db_uint8 : db_int8; break; case SQL_SMALLINT: - type = is_unsigned == SQL_TRUE ? dt_uint16 : dt_int16; + type = dt_integer; + dbtype = is_unsigned == SQL_TRUE ? db_uint16 : db_int16; break; case SQL_INTEGER: - type = is_unsigned == SQL_TRUE ? dt_uint32 : dt_int32; + type = dt_integer; + dbtype = is_unsigned == SQL_TRUE ? db_uint32 : db_int32; break; case SQL_BIGINT: - type = is_unsigned == SQL_TRUE ? dt_uint64 : dt_int64; + type = dt_long_long; + dbtype = is_unsigned == SQL_TRUE ? db_uint64 : db_int64; break; case SQL_CHAR: case SQL_VARCHAR: case SQL_LONGVARCHAR: default: type = dt_string; + dbtype = db_string; break; } } diff --git a/src/backends/oracle/statement.cpp b/src/backends/oracle/statement.cpp index d6fa5f68e..4a506bc71 100644 --- a/src/backends/oracle/statement.cpp +++ b/src/backends/oracle/statement.cpp @@ -185,6 +185,7 @@ int oracle_statement_backend::prepare_for_describe() } void oracle_statement_backend::describe_column(int colNum, data_type &type, + db_type &xdbtype, std::string &columnName) { ub2 dbtype; @@ -286,6 +287,7 @@ void oracle_statement_backend::describe_column(int colNum, data_type &type, case SQLT_CHR: case SQLT_AFC: type = dt_string; + xdbtype = db_string; break; case SQLT_NUM: if (dbscale > 0) @@ -293,30 +295,37 @@ void oracle_statement_backend::describe_column(int colNum, data_type &type, if (session_.get_option_decimals_as_strings()) { type = dt_string; + xdbtype = db_string; } else { type = dt_double; + xdbtype = db_double; } } else if (dbprec <= std::numeric_limits::digits10) { - type = dt_int32; + type = dt_integer; + xdbtype = db_int32; } else { - type = dt_int64; + type = dt_long_long; + xdbtype = db_int64; } break; case OCI_TYPECODE_BDOUBLE: type = dt_double; + xdbtype = db_double; break; case SQLT_DAT: type = dt_date; + xdbtype = db_date; break; default: // Unknown oracle types will just be represented by a string type = dt_string; + xdbtype = db_string; } } diff --git a/src/backends/postgresql/statement.cpp b/src/backends/postgresql/statement.cpp index abd2a68cf..388661094 100644 --- a/src/backends/postgresql/statement.cpp +++ b/src/backends/postgresql/statement.cpp @@ -741,7 +741,7 @@ void throw_soci_type_error(Oid typeOid, int colNum, char category, const char* t } void postgresql_statement_backend::describe_column(int colNum, data_type & type, - std::string & columnName) + db_type & dbtype, std::string & columnName) { // In postgresql_ column numbers start from 0 int const pos = colNum - 1; @@ -765,6 +765,7 @@ void postgresql_statement_backend::describe_column(int colNum, data_type & type, case 17: // bytea case 2950: // uuid type = dt_string; + dbtype = db_string; break; case 702: // abstime @@ -775,29 +776,35 @@ void postgresql_statement_backend::describe_column(int colNum, data_type & type, case 1184: // timestamptz case 1266: // timetz type = dt_date; + dbtype = db_date; break; case 700: // float4 case 701: // float8 case 1700: // numeric type = dt_double; + dbtype = db_double; break; case 16: // bool - type = dt_int8; + type = dt_integer; + dbtype = db_int8; break; case 21: // int2 - type = dt_int16; + type = dt_integer; + dbtype = db_int16; break; case 23: // int4 case 26: // oid - type = dt_int32; + type = dt_integer; + dbtype = db_int32; break; case 20: // int8 - type = dt_int64; + type = dt_long_long; + dbtype = db_int64; break; default: @@ -833,6 +840,7 @@ void postgresql_statement_backend::describe_column(int colNum, data_type & type, case 'S': // string type case 'U': // user type type = dt_string; + dbtype = db_string; break; default: diff --git a/src/backends/sqlite3/standard-use-type.cpp b/src/backends/sqlite3/standard-use-type.cpp index c8d502545..016f4da6e 100644 --- a/src/backends/sqlite3/standard-use-type.cpp +++ b/src/backends/sqlite3/standard-use-type.cpp @@ -99,6 +99,7 @@ void sqlite3_standard_use_type_backend::pre_use(indicator const * ind) { case x_char: col.type_ = dt_string; + col.dataType_ = db_string; col.buffer_.constData_ = &exchange_type_cast(data_); col.buffer_.size_ = 1; break; @@ -107,59 +108,70 @@ void sqlite3_standard_use_type_backend::pre_use(indicator const * ind) { const std::string &s = exchange_type_cast(data_); col.type_ = dt_string; + col.dataType_ = db_string; col.buffer_.constData_ = s.c_str(); col.buffer_.size_ = s.size(); break; } case x_int8: - col.type_ = dt_int8; + col.type_ = dt_integer; + col.dataType_ = db_int8; col.int8_ = exchange_type_cast(data_); break; case x_uint8: - col.type_ = dt_uint8; + col.type_ = dt_integer; + col.dataType_ = db_uint8; col.uint8_ = exchange_type_cast(data_); break; case x_int16: - col.type_ = dt_int16; + col.type_ = dt_integer; + col.dataType_ = db_int16; col.int16_ = exchange_type_cast(data_); break; case x_uint16: - col.type_ = dt_uint16; + col.type_ = dt_integer; + col.dataType_ = db_uint16; col.uint16_ = exchange_type_cast(data_); break; case x_int32: - col.type_ = dt_int32; + col.type_ = dt_integer; + col.dataType_ = db_int32; col.int32_ = exchange_type_cast(data_); break; case x_uint32: - col.type_ = dt_uint32; + col.type_ = dt_long_long; + col.dataType_ = db_uint32; col.uint32_ = exchange_type_cast(data_); break; case x_int64: - col.type_ = dt_int64; + col.type_ = dt_long_long; + col.dataType_ = db_int64; col.int64_ = exchange_type_cast(data_); break; case x_uint64: - col.type_ = dt_uint64; + col.type_ = dt_unsigned_long_long; + col.dataType_ = db_uint64; col.uint64_ = exchange_type_cast(data_); break; case x_double: col.type_ = dt_double; + col.dataType_ = db_double; col.double_ = exchange_type_cast(data_); break; case x_stdtm: { col.type_ = dt_date; + col.dataType_ = db_date; static const size_t bufSize = 20; std::tm &t = exchange_type_cast(data_); @@ -175,7 +187,8 @@ void sqlite3_standard_use_type_backend::pre_use(indicator const * ind) case x_rowid: { - col.type_ = dt_int64; + col.type_ = dt_long_long; + col.dataType_ = db_int64; // RowID is internally identical to unsigned long rowid *rid = static_cast(data_); sqlite3_rowid_backend *rbe = static_cast(rid->get_backend()); @@ -187,6 +200,7 @@ void sqlite3_standard_use_type_backend::pre_use(indicator const * ind) case x_blob: { col.type_ = dt_blob; + col.dataType_ = db_blob; blob *b = static_cast(data_); sqlite3_blob_backend *bbe = static_cast(b->get_backend()); @@ -199,6 +213,7 @@ void sqlite3_standard_use_type_backend::pre_use(indicator const * ind) { const soci::xml_type &xml = exchange_type_cast(data_); col.type_ = dt_string; + col.dataType_ = db_string; col.buffer_.constData_ = xml.value.c_str(); col.buffer_.size_ = xml.value.size(); break; diff --git a/src/backends/sqlite3/statement.cpp b/src/backends/sqlite3/statement.cpp index 19c4fc437..8b1db7145 100644 --- a/src/backends/sqlite3/statement.cpp +++ b/src/backends/sqlite3/statement.cpp @@ -117,9 +117,10 @@ sqlite3_statement_backend::load_rowset(int totalRows) { numCols = sqlite3_column_count(stmt_); data_type type; + db_type dbtype; std::string name; for (int c = 1; c <= numCols; ++c) - describe_column(c, type, name); + describe_column(c, type, dbtype, name); } else numCols = static_cast(columns_.size()); @@ -164,52 +165,53 @@ sqlite3_statement_backend::load_rowset(int totalRows) col.isNull_ = false; col.type_ = coldef.type_; + col.dataType_ = coldef.dataType_; - switch (coldef.type_) + switch (coldef.dataType_) { - case dt_string: - case dt_date: + case db_string: + case db_date: col.buffer_.size_ = sqlite3_column_bytes(stmt_, c); col.buffer_.data_ = new char[col.buffer_.size_+1]; memcpy(col.buffer_.data_, sqlite3_column_text(stmt_, c), col.buffer_.size_+1); break; - case dt_double: + case db_double: col.double_ = sqlite3_column_double(stmt_, c); break; - case dt_int8: + case db_int8: col.int8_ = static_cast(sqlite3_column_int(stmt_, c)); break; - case dt_uint8: + case db_uint8: col.uint8_ = static_cast(sqlite3_column_int(stmt_, c)); break; - case dt_int16: + case db_int16: col.int16_ = static_cast(sqlite3_column_int(stmt_, c)); break; - case dt_uint16: + case db_uint16: col.uint16_ = static_cast(sqlite3_column_int(stmt_, c)); break; - case dt_int32: + case db_int32: col.int32_ = static_cast(sqlite3_column_int(stmt_, c)); break; - case dt_uint32: + case db_uint32: col.uint32_ = static_cast(sqlite3_column_int(stmt_, c)); break; - case dt_int64: + case db_int64: col.int64_ = sqlite3_column_int64(stmt_, c); break; - case dt_uint64: + case db_uint64: col.uint64_ = static_cast(sqlite3_column_int64(stmt_, c)); break; - case dt_blob: + case db_blob: col.buffer_.size_ = sqlite3_column_bytes(stmt_, c); col.buffer_.data_ = (col.buffer_.size_ > 0 ? new char[col.buffer_.size_] : NULL); memcpy(col.buffer_.data_, sqlite3_column_blob(stmt_, c), col.buffer_.size_); break; - case dt_xml: + case db_xml: throw soci_error("XML data type is not supported"); } } @@ -286,50 +288,50 @@ sqlite3_statement_backend::bind_and_execute(int number) } else { - switch (col.type_) + switch (col.dataType_) { - case dt_string: + case db_string: bindRes = sqlite3_bind_text(stmt_, pos, col.buffer_.constData_, static_cast(col.buffer_.size_), NULL); break; - case dt_date: + case db_date: bindRes = sqlite3_bind_text(stmt_, pos, col.buffer_.constData_, static_cast(col.buffer_.size_), SQLITE_TRANSIENT); break; - case dt_double: + case db_double: bindRes = sqlite3_bind_double(stmt_, pos, col.double_); break; - case dt_int8: + case db_int8: bindRes = sqlite3_bind_int(stmt_, pos, static_cast(col.int8_)); break; - case dt_uint8: + case db_uint8: bindRes = sqlite3_bind_int(stmt_, pos, static_cast(col.uint8_)); break; - case dt_int16: + case db_int16: bindRes = sqlite3_bind_int(stmt_, pos, static_cast(col.int16_)); break; - case dt_uint16: + case db_uint16: bindRes = sqlite3_bind_int(stmt_, pos, static_cast(col.uint16_)); break; - case dt_int32: + case db_int32: bindRes = sqlite3_bind_int(stmt_, pos, static_cast(col.int32_)); break; - case dt_uint32: + case db_uint32: bindRes = sqlite3_bind_int64(stmt_, pos, static_cast(col.uint32_)); break; - case dt_int64: + case db_int64: bindRes = sqlite3_bind_int64(stmt_, pos, col.int64_); break; - case dt_uint64: + case db_uint64: bindRes = sqlite3_bind_int64(stmt_, pos, static_cast(col.int64_)); break; - case dt_blob: + case db_blob: bindRes = sqlite3_bind_blob(stmt_, pos, col.buffer_.constData_, static_cast(col.buffer_.size_), NULL); break; - case dt_xml: + case db_xml: throw soci_error("XML data type is not supported"); } } @@ -441,67 +443,58 @@ int sqlite3_statement_backend::prepare_for_describe() return sqlite3_column_count(stmt_); } -typedef std::map sqlite3_data_type_map; +typedef std::map> sqlite3_data_type_map; static sqlite3_data_type_map get_data_type_map() { sqlite3_data_type_map m; // Spaces are removed from decltype before looking up in this map, so we don't use them here as well - // dt_blob - m["blob"] = dt_blob; - - // dt_date - m["date"] = dt_date; - m["time"] = dt_date; - m["datetime"] = dt_date; - m["timestamp"] = dt_date; - - // dt_double - m["decimal"] = dt_double; - m["double"] = dt_double; - m["doubleprecision"] = dt_double; - m["float"] = dt_double; - m["number"] = dt_double; - m["numeric"] = dt_double; - m["real"] = dt_double; - - // dt_int8 - m["tinyint"] = dt_int8; - - // dt_int16 - m["smallint"] = dt_int16; - - // dt_int32 - m["boolean"] = dt_int32; - m["int"] = dt_int32; - m["integer"] = dt_int32; - m["int2"] = dt_int32; - m["mediumint"] = dt_int32; - - // dt_int64 - m["bigint"] = dt_int64; - m["int8"] = dt_int64; - - // dt_string - m["char"] = dt_string; - m["character"] = dt_string; - m["clob"] = dt_string; - m["nativecharacter"] = dt_string; - m["nchar"] = dt_string; - m["nvarchar"] = dt_string; - m["text"] = dt_string; - m["varchar"] = dt_string; - m["varyingcharacter"] = dt_string; - - // dt_uint64 - m["unsignedbigint"] = dt_uint64; + m["blob"] = { dt_blob, db_blob }; + m["date"] = { dt_date, db_date }; + m["time"] = { dt_date, db_date }; + m["datetime"] = { dt_date, db_date }; + m["timestamp"] = { dt_date, db_date }; + + m["decimal"] = { dt_double, db_double }; + m["double"] = { dt_double, db_double }; + m["doubleprecision"] = { dt_double, db_double }; + m["float"] = { dt_double, db_double }; + m["number"] = { dt_double, db_double }; + m["numeric"] = { dt_double, db_double }; + m["real"] = { dt_double, db_double }; + + m["tinyint"] = { dt_integer, db_int8 }; + + m["smallint"] = { dt_integer, db_int16 }; + + m["boolean"] = { dt_integer, db_int32 }; + m["int"] = { dt_integer, db_int32 }; + m["integer"] = { dt_integer, db_int32 }; + m["int2"] = { dt_integer, db_int32 }; + m["mediumint"] = { dt_integer, db_int32 }; + + m["bigint"] = { dt_long_long, db_int64 }; + m["int8"] = { dt_long_long, db_int64 }; + + m["char"] = { dt_string, db_string }; + m["character"] = { dt_string, db_string }; + m["clob"] = { dt_string, db_string }; + m["nativecharacter"] = { dt_string, db_string }; + m["nchar"] = { dt_string, db_string }; + m["nvarchar"] = { dt_string, db_string }; + m["text"] = { dt_string, db_string }; + m["varchar"] = { dt_string, db_string }; + m["varyingcharacter"] = { dt_string, db_string }; + + m["unsignedbigint"] = { dt_unsigned_long_long, db_uint64 }; return m; } void sqlite3_statement_backend::describe_column(int colNum, data_type & type, + db_type & dbtype, std::string & columnName) { static const sqlite3_data_type_map dataTypeMap = get_data_type_map(); @@ -514,6 +507,7 @@ void sqlite3_statement_backend::describe_column(int colNum, data_type & type, { columnName = coldef.name_; type = coldef.type_; + dbtype = coldef.dataType_; return; } @@ -547,7 +541,8 @@ void sqlite3_statement_backend::describe_column(int colNum, data_type & type, sqlite3_data_type_map::const_iterator iter = dataTypeMap.find(dt); if (iter != dataTypeMap.end()) { - coldef.type_ = type = iter->second; + coldef.type_ = type = iter->second.first; + coldef.dataType_ = dbtype = iter->second.second; return; } @@ -561,20 +556,25 @@ void sqlite3_statement_backend::describe_column(int colNum, data_type & type, switch (sqlite3_type) { case SQLITE_INTEGER: - type = dt_int32; + type = dt_integer; + dbtype = db_int32; break; case SQLITE_FLOAT: type = dt_double; + dbtype = db_double; break; case SQLITE_BLOB: case SQLITE_TEXT: type = dt_string; + dbtype = db_string; break; default: type = dt_string; + dbtype = db_string; break; } coldef.type_ = type; + coldef.dataType_ = dbtype; sqlite3_reset(stmt_); } diff --git a/src/backends/sqlite3/vector-into-type.cpp b/src/backends/sqlite3/vector-into-type.cpp index 14fd587c0..fb67a252d 100644 --- a/src/backends/sqlite3/vector-into-type.cpp +++ b/src/backends/sqlite3/vector-into-type.cpp @@ -88,47 +88,47 @@ void set_number_in_vector(void *p, int idx, const sqlite3_column &col) using namespace details; using namespace details::sqlite3; - switch (col.type_) + switch (col.dataType_) { - case dt_date: - case dt_string: - case dt_blob: + case db_date: + case db_string: + case db_blob: set_in_vector(p, idx, parse_number_from_string(col.buffer_.size_ > 0 ? col.buffer_.constData_ : "")); break; - case dt_double: + case db_double: set_in_vector(p, idx, static_cast(col.double_)); break; - case dt_int8: + case db_int8: set_in_vector(p, idx, static_cast(col.int8_)); break; - case dt_uint8: + case db_uint8: set_in_vector(p, idx, static_cast(col.uint8_)); break; - case dt_int16: + case db_int16: set_in_vector(p, idx, static_cast(col.int16_)); break; - case dt_uint16: + case db_uint16: set_in_vector(p, idx, static_cast(col.uint16_)); break; - case dt_int32: + case db_int32: set_in_vector(p, idx, static_cast(col.int32_)); break; - case dt_uint32: + case db_uint32: set_in_vector(p, idx, static_cast(col.uint32_)); break; - case dt_int64: + case db_int64: set_in_vector(p, idx, static_cast(col.int64_)); break; - case dt_uint64: + case db_uint64: set_in_vector(p, idx, static_cast(col.uint64_)); break; - case dt_xml: + case db_xml: throw soci_error("XML data type is not supported"); }; } @@ -172,68 +172,68 @@ void sqlite3_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) { case x_char: { - switch (col.type_) + switch (col.dataType_) { - case dt_date: - case dt_string: - case dt_blob: + case db_date: + case db_string: + case db_blob: set_in_vector(data_, i, (col.buffer_.size_ > 0 ? col.buffer_.constData_[0] : '\0')); break; - case dt_double: + case db_double: set_in_vector(data_, i, double_to_cstring(col.double_)[0]); break; - case dt_int8: + case db_int8: { std::ostringstream ss; ss << col.int8_; set_in_vector(data_, i, ss.str()[0]); break; } - case dt_uint8: + case db_uint8: { std::ostringstream ss; ss << col.uint8_; set_in_vector(data_, i, ss.str()[0]); break; } - case dt_int16: + case db_int16: { std::ostringstream ss; ss << col.int16_; set_in_vector(data_, i, ss.str()[0]); break; } - case dt_uint16: + case db_uint16: { std::ostringstream ss; ss << col.uint16_; set_in_vector(data_, i, ss.str()[0]); break; } - case dt_int32: + case db_int32: { std::ostringstream ss; ss << col.int32_; set_in_vector(data_, i, ss.str()[0]); break; } - case dt_uint32: + case db_uint32: { std::ostringstream ss; ss << col.uint32_; set_in_vector(data_, i, ss.str()[0]); break; } - case dt_int64: + case db_int64: { std::ostringstream ss; ss << col.int64_; set_in_vector(data_, i, ss.str()[0]); break; } - case dt_uint64: + case db_uint64: { std::ostringstream ss; ss << col.uint64_; @@ -241,7 +241,7 @@ void sqlite3_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) break; } - case dt_xml: + case db_xml: throw soci_error("XML data type is not supported"); }; break; @@ -249,68 +249,68 @@ void sqlite3_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) case x_stdstring: { - switch (col.type_) + switch (col.dataType_) { - case dt_date: - case dt_string: - case dt_blob: + case db_date: + case db_string: + case db_blob: set_in_vector(data_, i, std::string(col.buffer_.constData_, col.buffer_.size_)); break; - case dt_double: + case db_double: set_in_vector(data_, i, double_to_cstring(col.double_)); break; - case dt_int8: + case db_int8: { std::ostringstream ss; ss << col.int8_; set_in_vector(data_, i, ss.str()); break; } - case dt_uint8: + case db_uint8: { std::ostringstream ss; ss << col.uint8_; set_in_vector(data_, i, ss.str()); break; } - case dt_int16: + case db_int16: { std::ostringstream ss; ss << col.int16_; set_in_vector(data_, i, ss.str()); break; } - case dt_uint16: + case db_uint16: { std::ostringstream ss; ss << col.uint16_; set_in_vector(data_, i, ss.str()); break; } - case dt_int32: + case db_int32: { std::ostringstream ss; ss << col.int32_; set_in_vector(data_, i, ss.str()); break; } - case dt_uint32: + case db_uint32: { std::ostringstream ss; ss << col.uint32_; set_in_vector(data_, i, ss.str()); break; } - case dt_int64: + case db_int64: { std::ostringstream ss; ss << col.int64_; set_in_vector(data_, i, ss.str()); break; } - case dt_uint64: + case db_uint64: { std::ostringstream ss; ss << col.uint64_; @@ -318,7 +318,7 @@ void sqlite3_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) break; } - case dt_xml: + case db_xml: { soci::xml_type xml; xml.value = std::string(col.buffer_.constData_, col.buffer_.size_); @@ -331,11 +331,11 @@ void sqlite3_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) case x_xmltype: { - switch (col.type_) + switch (col.dataType_) { - case dt_string: - case dt_blob: - case dt_xml: + case db_string: + case db_blob: + case db_xml: { soci::xml_type xml; xml.value = std::string(col.buffer_.constData_, col.buffer_.size_); @@ -386,11 +386,11 @@ void sqlite3_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) case x_stdtm: { - switch (col.type_) + switch (col.dataType_) { - case dt_date: - case dt_string: - case dt_blob: + case db_date: + case db_string: + case db_blob: { // attempt to parse the string and convert to std::tm std::tm t = std::tm(); @@ -400,18 +400,18 @@ void sqlite3_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) break; } - case dt_double: - case dt_int8: - case dt_uint8: - case dt_int16: - case dt_uint16: - case dt_int32: - case dt_uint32: - case dt_int64: - case dt_uint64: + case db_double: + case db_int8: + case db_uint8: + case db_int16: + case db_uint16: + case db_int32: + case db_uint32: + case db_int64: + case db_uint64: throw soci_error("Into element used with non-convertible type."); - case dt_xml: + case db_xml: throw soci_error("XML data type is not supported"); }; break; @@ -422,27 +422,27 @@ void sqlite3_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) } // cleanup data - switch (col.type_) + switch (col.dataType_) { - case dt_date: - case dt_string: - case dt_blob: + case db_date: + case db_string: + case db_blob: delete[] col.buffer_.data_; col.buffer_.data_ = NULL; break; - case dt_double: - case dt_int8: - case dt_uint8: - case dt_int16: - case dt_uint16: - case dt_int32: - case dt_uint32: - case dt_int64: - case dt_uint64: + case db_double: + case db_int8: + case db_uint8: + case db_int16: + case db_uint16: + case db_int32: + case db_uint32: + case db_int64: + case db_uint64: break; - case dt_xml: + case db_xml: throw soci_error("XML data type is not supported"); } } diff --git a/src/backends/sqlite3/vector-use-type.cpp b/src/backends/sqlite3/vector-use-type.cpp index b07a9afc5..71c2ea624 100644 --- a/src/backends/sqlite3/vector-use-type.cpp +++ b/src/backends/sqlite3/vector-use-type.cpp @@ -99,6 +99,7 @@ void sqlite3_vector_use_type_backend::pre_use(indicator const * ind) { case x_char: col.type_ = dt_string; + col.dataType_ = db_string; col.buffer_.constData_ = &(*static_cast::value_type> *>(data_))[i]; col.buffer_.size_ = 1; break; @@ -107,53 +108,63 @@ void sqlite3_vector_use_type_backend::pre_use(indicator const * ind) { std::string &s = (*static_cast::value_type> *>(data_))[i]; col.type_ = dt_string; + col.dataType_ = db_string; col.buffer_.constData_ = s.c_str(); col.buffer_.size_ = s.size(); break; } case x_int8: - col.type_ = dt_int8; + col.type_ = dt_integer; + col.dataType_ = db_int8; col.int8_ = (*static_cast::value_type> *>(data_))[i]; break; case x_uint8: - col.type_ = dt_uint8; + col.type_ = dt_integer; + col.dataType_ = db_uint8; col.uint8_ = (*static_cast::value_type> *>(data_))[i]; break; case x_int16: - col.type_ = dt_int16; + col.type_ = dt_integer; + col.dataType_ = db_int16; col.int16_ = (*static_cast::value_type> *>(data_))[i]; break; case x_uint16: - col.type_ = dt_uint16; + col.type_ = dt_integer; + col.dataType_ = db_uint16; col.uint16_ = (*static_cast::value_type> *>(data_))[i]; break; case x_int32: - col.type_ = dt_int32; + col.type_ = dt_integer; + col.dataType_ = db_int32; col.int32_ = (*static_cast::value_type> *>(data_))[i]; break; case x_uint32: - col.type_ = dt_uint32; + col.type_ = dt_long_long; + col.dataType_ = db_uint32; col.uint32_ = (*static_cast::value_type> *>(data_))[i]; break; case x_int64: - col.type_ = dt_int64; + col.type_ = dt_long_long; + col.dataType_ = db_int64; col.int64_ = (*static_cast::value_type> *>(data_))[i]; break; case x_uint64: - col.type_ = dt_uint64; + col.type_ = dt_unsigned_long_long; + col.dataType_ = db_uint64; col.uint64_ = (*static_cast::value_type> *>(data_))[i]; break; case x_double: col.type_ = dt_double; + col.dataType_ = db_double; col.double_ = (*static_cast::value_type> *>(data_))[i]; break; @@ -163,6 +174,7 @@ void sqlite3_vector_use_type_backend::pre_use(indicator const * ind) static const size_t bufSize = 20; col.type_ = dt_date; + col.dataType_ = db_date; col.buffer_.data_ = new char[bufSize]; col.buffer_.size_ = snprintf(col.buffer_.data_, bufSize, "%d-%02d-%02d %02d:%02d:%02d", @@ -176,6 +188,7 @@ void sqlite3_vector_use_type_backend::pre_use(indicator const * ind) { soci::xml_type &xml = (*static_cast::value_type> *>(data_))[i]; col.type_ = dt_string; + col.dataType_ = db_string; col.buffer_.constData_ = xml.value.c_str(); col.buffer_.size_ = xml.value.size(); break; diff --git a/src/core/once-temp-type.cpp b/src/core/once-temp-type.cpp index 6fd189f68..5e3597c62 100644 --- a/src/core/once-temp-type.cpp +++ b/src/core/once-temp-type.cpp @@ -126,6 +126,24 @@ ddl_type & ddl_type::column(const std::string & columnName, data_type dt, return *this; } +ddl_type & ddl_type::column(const std::string & columnName, db_type dt, + int precision, int scale) +{ + if (rcst_->get_need_comma()) + { + rcst_->accumulate(", "); + } + + rcst_->accumulate(columnName); + rcst_->accumulate(" "); + rcst_->accumulate( + s_->get_backend()->create_column_type(dt, precision, scale)); + + rcst_->set_need_comma(true); + + return *this; +} + ddl_type & ddl_type::unique(const std::string & name, const std::string & columnNames) { diff --git a/src/core/soci-simple.cpp b/src/core/soci-simple.cpp index 834f89a5a..99397ec8a 100644 --- a/src/core/soci-simple.cpp +++ b/src/core/soci-simple.cpp @@ -353,7 +353,7 @@ struct statement_wrapper // into elements int next_position; - std::vector into_types; // for both single and bulk + std::vector into_types; // for both single and bulk std::vector into_indicators; std::map into_strings; std::map into_int8; @@ -488,7 +488,7 @@ bool cannot_add_elements(statement_wrapper & wrapper, statement_wrapper::kind k, // helper for checking if the expected into element exists on the given position bool position_check_failed(statement_wrapper & wrapper, statement_wrapper::kind k, - int position, data_type expected_type, char const * type_name) + int position, db_type expected_type, char const * type_name) { if (position < 0 || position >= wrapper.next_position) { @@ -599,7 +599,7 @@ bool name_unique_check_failed(statement_wrapper & wrapper, // helper for checking if the use element with the given name exists bool name_exists_check_failed(statement_wrapper & wrapper, - char const * name, data_type expected_type, + char const * name, db_type expected_type, statement_wrapper::kind k, char const * type_name) { bool name_exists = false; @@ -607,7 +607,7 @@ bool name_exists_check_failed(statement_wrapper & wrapper, { switch (expected_type) { - case dt_string: + case db_string: { typedef std::map < @@ -618,49 +618,49 @@ bool name_exists_check_failed(statement_wrapper & wrapper, name_exists = (it != wrapper.use_strings.end()); } break; - case dt_int8: + case db_int8: { typedef std::map::const_iterator iterator; iterator const it = wrapper.use_int8.find(name); name_exists = (it != wrapper.use_int8.end()); } break; - case dt_uint8: + case db_uint8: { typedef std::map::const_iterator iterator; iterator const it = wrapper.use_uint8.find(name); name_exists = (it != wrapper.use_uint8.end()); } break; - case dt_int16: + case db_int16: { typedef std::map::const_iterator iterator; iterator const it = wrapper.use_int16.find(name); name_exists = (it != wrapper.use_int16.end()); } break; - case dt_uint16: + case db_uint16: { typedef std::map::const_iterator iterator; iterator const it = wrapper.use_uint16.find(name); name_exists = (it != wrapper.use_uint16.end()); } break; - case dt_int32: + case db_int32: { typedef std::map::const_iterator iterator; iterator const it = wrapper.use_int32.find(name); name_exists = (it != wrapper.use_int32.end()); } break; - case dt_uint32: + case db_uint32: { typedef std::map::const_iterator iterator; iterator const it = wrapper.use_uint32.find(name); name_exists = (it != wrapper.use_uint32.end()); } break; - case dt_int64: + case db_int64: { typedef std::map::const_iterator iterator; @@ -668,7 +668,7 @@ bool name_exists_check_failed(statement_wrapper & wrapper, name_exists = (it != wrapper.use_int64.end()); } break; - case dt_uint64: + case db_uint64: { typedef std::map::const_iterator iterator; @@ -676,27 +676,27 @@ bool name_exists_check_failed(statement_wrapper & wrapper, name_exists = (it != wrapper.use_uint64.end()); } break; - case dt_double: + case db_double: { typedef std::map::const_iterator iterator; iterator const it = wrapper.use_doubles.find(name); name_exists = (it != wrapper.use_doubles.end()); } break; - case dt_date: + case db_date: { typedef std::map::const_iterator iterator; iterator const it = wrapper.use_dates.find(name); name_exists = (it != wrapper.use_dates.end()); } break; - case dt_blob: + case db_blob: { typedef std::map::const_iterator iterator; iterator const it = wrapper.use_blob.find(name); name_exists = (it != wrapper.use_blob.end()); } - case dt_xml: + case db_xml: // no support for xml break; } @@ -707,7 +707,7 @@ bool name_exists_check_failed(statement_wrapper & wrapper, switch (expected_type) { - case dt_string: + case db_string: { typedef std::map < @@ -718,7 +718,7 @@ bool name_exists_check_failed(statement_wrapper & wrapper, name_exists = (it != wrapper.use_strings_v.end()); } break; - case dt_int8: + case db_int8: { typedef std::map < @@ -729,7 +729,7 @@ bool name_exists_check_failed(statement_wrapper & wrapper, name_exists = (it != wrapper.use_int8_v.end()); } break; - case dt_uint8: + case db_uint8: { typedef std::map < @@ -740,7 +740,7 @@ bool name_exists_check_failed(statement_wrapper & wrapper, name_exists = (it != wrapper.use_uint8_v.end()); } break; - case dt_int16: + case db_int16: { typedef std::map < @@ -751,7 +751,7 @@ bool name_exists_check_failed(statement_wrapper & wrapper, name_exists = (it != wrapper.use_int16_v.end()); } break; - case dt_uint16: + case db_uint16: { typedef std::map < @@ -762,7 +762,7 @@ bool name_exists_check_failed(statement_wrapper & wrapper, name_exists = (it != wrapper.use_uint16_v.end()); } break; - case dt_int32: + case db_int32: { typedef std::map < @@ -773,7 +773,7 @@ bool name_exists_check_failed(statement_wrapper & wrapper, name_exists = (it != wrapper.use_int32_v.end()); } break; - case dt_uint32: + case db_uint32: { typedef std::map < @@ -784,7 +784,7 @@ bool name_exists_check_failed(statement_wrapper & wrapper, name_exists = (it != wrapper.use_uint32_v.end()); } break; - case dt_int64: + case db_int64: { typedef std::map < @@ -795,7 +795,7 @@ bool name_exists_check_failed(statement_wrapper & wrapper, name_exists = (it != wrapper.use_int64_v.end()); } break; - case dt_uint64: + case db_uint64: { typedef std::map < @@ -806,7 +806,7 @@ bool name_exists_check_failed(statement_wrapper & wrapper, name_exists = (it != wrapper.use_uint64_v.end()); } break; - case dt_double: + case db_double: { typedef std::map >::const_iterator iterator; @@ -814,7 +814,7 @@ bool name_exists_check_failed(statement_wrapper & wrapper, name_exists = (it != wrapper.use_doubles_v.end()); } break; - case dt_date: + case db_date: { typedef std::map >::const_iterator iterator; @@ -822,8 +822,8 @@ bool name_exists_check_failed(statement_wrapper & wrapper, name_exists = (it != wrapper.use_dates_v.end()); } break; - case dt_blob: - case dt_xml: + case db_blob: + case db_xml: // no support for bulk and xml load break; } @@ -936,7 +936,7 @@ SOCI_DECL int soci_into_string(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::single; - wrapper->into_types.push_back(dt_string); + wrapper->into_types.push_back(db_string); wrapper->into_indicators.push_back(i_ok); wrapper->into_strings[wrapper->next_position]; // create new entry return wrapper->next_position++; @@ -964,7 +964,7 @@ SOCI_DECL int soci_into_int8(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::single; - wrapper->into_types.push_back(dt_int8); + wrapper->into_types.push_back(db_int8); wrapper->into_indicators.push_back(i_ok); wrapper->into_int8[wrapper->next_position]; // create new entry return wrapper->next_position++; @@ -982,7 +982,7 @@ SOCI_DECL int soci_into_uint8(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::single; - wrapper->into_types.push_back(dt_uint8); + wrapper->into_types.push_back(db_uint8); wrapper->into_indicators.push_back(i_ok); wrapper->into_uint8[wrapper->next_position]; // create new entry return wrapper->next_position++; @@ -1000,7 +1000,7 @@ SOCI_DECL int soci_into_int16(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::single; - wrapper->into_types.push_back(dt_int16); + wrapper->into_types.push_back(db_int16); wrapper->into_indicators.push_back(i_ok); wrapper->into_int16[wrapper->next_position]; // create new entry return wrapper->next_position++; @@ -1018,7 +1018,7 @@ SOCI_DECL int soci_into_uint16(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::single; - wrapper->into_types.push_back(dt_uint16); + wrapper->into_types.push_back(db_uint16); wrapper->into_indicators.push_back(i_ok); wrapper->into_uint16[wrapper->next_position]; // create new entry return wrapper->next_position++; @@ -1036,7 +1036,7 @@ SOCI_DECL int soci_into_int32(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::single; - wrapper->into_types.push_back(dt_int32); + wrapper->into_types.push_back(db_int32); wrapper->into_indicators.push_back(i_ok); wrapper->into_int32[wrapper->next_position]; // create new entry return wrapper->next_position++; @@ -1054,7 +1054,7 @@ SOCI_DECL int soci_into_uint32(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::single; - wrapper->into_types.push_back(dt_uint32); + wrapper->into_types.push_back(db_uint32); wrapper->into_indicators.push_back(i_ok); wrapper->into_uint32[wrapper->next_position]; // create new entry return wrapper->next_position++; @@ -1072,7 +1072,7 @@ SOCI_DECL int soci_into_int64(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::single; - wrapper->into_types.push_back(dt_int64); + wrapper->into_types.push_back(db_int64); wrapper->into_indicators.push_back(i_ok); wrapper->into_int64[wrapper->next_position]; // create new entry return wrapper->next_position++; @@ -1090,7 +1090,7 @@ SOCI_DECL int soci_into_uint64(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::single; - wrapper->into_types.push_back(dt_uint64); + wrapper->into_types.push_back(db_uint64); wrapper->into_indicators.push_back(i_ok); wrapper->into_uint64[wrapper->next_position]; // create new entry return wrapper->next_position++; @@ -1108,7 +1108,7 @@ SOCI_DECL int soci_into_double(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::single; - wrapper->into_types.push_back(dt_double); + wrapper->into_types.push_back(db_double); wrapper->into_indicators.push_back(i_ok); wrapper->into_doubles[wrapper->next_position]; // create new entry return wrapper->next_position++; @@ -1126,7 +1126,7 @@ SOCI_DECL int soci_into_date(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::single; - wrapper->into_types.push_back(dt_date); + wrapper->into_types.push_back(db_date); wrapper->into_indicators.push_back(i_ok); wrapper->into_dates[wrapper->next_position]; // create new entry return wrapper->next_position++; @@ -1144,7 +1144,7 @@ SOCI_DECL int soci_into_blob(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::single; - wrapper->into_types.push_back(dt_blob); + wrapper->into_types.push_back(db_blob); wrapper->into_indicators.push_back(i_ok); wrapper->into_blob[wrapper->next_position] = soci_create_blob_session(wrapper->sql); // create new entry return wrapper->next_position++; @@ -1162,7 +1162,7 @@ SOCI_DECL int soci_into_string_v(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::bulk; - wrapper->into_types.push_back(dt_string); + wrapper->into_types.push_back(db_string); wrapper->into_indicators_v.push_back(std::vector()); wrapper->into_strings_v[wrapper->next_position]; return wrapper->next_position++; @@ -1190,7 +1190,7 @@ SOCI_DECL int soci_into_int8_v(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::bulk; - wrapper->into_types.push_back(dt_int8); + wrapper->into_types.push_back(db_int8); wrapper->into_indicators_v.push_back(std::vector()); wrapper->into_int8_v[wrapper->next_position]; return wrapper->next_position++; @@ -1208,7 +1208,7 @@ SOCI_DECL int soci_into_uint8_v(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::bulk; - wrapper->into_types.push_back(dt_uint8); + wrapper->into_types.push_back(db_uint8); wrapper->into_indicators_v.push_back(std::vector()); wrapper->into_uint8_v[wrapper->next_position]; return wrapper->next_position++; @@ -1226,7 +1226,7 @@ SOCI_DECL int soci_into_int16_v(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::bulk; - wrapper->into_types.push_back(dt_int16); + wrapper->into_types.push_back(db_int16); wrapper->into_indicators_v.push_back(std::vector()); wrapper->into_int16_v[wrapper->next_position]; return wrapper->next_position++; @@ -1244,7 +1244,7 @@ SOCI_DECL int soci_into_uint16_v(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::bulk; - wrapper->into_types.push_back(dt_uint16); + wrapper->into_types.push_back(db_uint16); wrapper->into_indicators_v.push_back(std::vector()); wrapper->into_uint16_v[wrapper->next_position]; return wrapper->next_position++; @@ -1262,7 +1262,7 @@ SOCI_DECL int soci_into_int32_v(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::bulk; - wrapper->into_types.push_back(dt_int32); + wrapper->into_types.push_back(db_int32); wrapper->into_indicators_v.push_back(std::vector()); wrapper->into_int32_v[wrapper->next_position]; return wrapper->next_position++; @@ -1280,7 +1280,7 @@ SOCI_DECL int soci_into_uint32_v(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::bulk; - wrapper->into_types.push_back(dt_uint32); + wrapper->into_types.push_back(db_uint32); wrapper->into_indicators_v.push_back(std::vector()); wrapper->into_uint32_v[wrapper->next_position]; return wrapper->next_position++; @@ -1298,7 +1298,7 @@ SOCI_DECL int soci_into_int64_v(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::bulk; - wrapper->into_types.push_back(dt_int64); + wrapper->into_types.push_back(db_int64); wrapper->into_indicators_v.push_back(std::vector()); wrapper->into_int64_v[wrapper->next_position]; return wrapper->next_position++; @@ -1316,7 +1316,7 @@ SOCI_DECL int soci_into_uint64_v(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::bulk; - wrapper->into_types.push_back(dt_uint64); + wrapper->into_types.push_back(db_uint64); wrapper->into_indicators_v.push_back(std::vector()); wrapper->into_uint64_v[wrapper->next_position]; return wrapper->next_position++; @@ -1334,7 +1334,7 @@ SOCI_DECL int soci_into_double_v(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::bulk; - wrapper->into_types.push_back(dt_double); + wrapper->into_types.push_back(db_double); wrapper->into_indicators_v.push_back(std::vector()); wrapper->into_doubles_v[wrapper->next_position]; return wrapper->next_position++; @@ -1352,7 +1352,7 @@ SOCI_DECL int soci_into_date_v(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::bulk; - wrapper->into_types.push_back(dt_date); + wrapper->into_types.push_back(db_date); wrapper->into_indicators_v.push_back(std::vector()); wrapper->into_dates_v[wrapper->next_position]; return wrapper->next_position++; @@ -1378,7 +1378,7 @@ SOCI_DECL char const * soci_get_into_string(statement_handle st, int position) statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::single, position, dt_string, "string") || + statement_wrapper::single, position, db_string, "string") || not_null_check_failed(*wrapper, position)) { return ""; @@ -1402,7 +1402,7 @@ SOCI_DECL int8_t soci_get_into_int8(statement_handle st, int position) statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::single, position, dt_int8, "int8") || + statement_wrapper::single, position, db_int8, "int8") || not_null_check_failed(*wrapper, position)) { return 0; @@ -1416,7 +1416,7 @@ SOCI_DECL uint8_t soci_get_into_uint8(statement_handle st, int position) statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::single, position, dt_uint8, "uint8") || + statement_wrapper::single, position, db_uint8, "uint8") || not_null_check_failed(*wrapper, position)) { return 0; @@ -1430,7 +1430,7 @@ SOCI_DECL int16_t soci_get_into_int16(statement_handle st, int position) statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::single, position, dt_int16, "int16") || + statement_wrapper::single, position, db_int16, "int16") || not_null_check_failed(*wrapper, position)) { return 0; @@ -1444,7 +1444,7 @@ SOCI_DECL uint16_t soci_get_into_uint16(statement_handle st, int position) statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::single, position, dt_uint16, "uint16") || + statement_wrapper::single, position, db_uint16, "uint16") || not_null_check_failed(*wrapper, position)) { return 0; @@ -1458,7 +1458,7 @@ SOCI_DECL int32_t soci_get_into_int32(statement_handle st, int position) statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::single, position, dt_int32, "int32") || + statement_wrapper::single, position, db_int32, "int32") || not_null_check_failed(*wrapper, position)) { return 0; @@ -1472,7 +1472,7 @@ SOCI_DECL uint32_t soci_get_into_uint32(statement_handle st, int position) statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::single, position, dt_uint32, "uint32") || + statement_wrapper::single, position, db_uint32, "uint32") || not_null_check_failed(*wrapper, position)) { return 0; @@ -1486,7 +1486,7 @@ SOCI_DECL int64_t soci_get_into_int64(statement_handle st, int position) statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::single, position, dt_int64, "int64") || + statement_wrapper::single, position, db_int64, "int64") || not_null_check_failed(*wrapper, position)) { return 0LL; @@ -1500,7 +1500,7 @@ SOCI_DECL uint64_t soci_get_into_uint64(statement_handle st, int position) statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::single, position, dt_uint64, "uint64") || + statement_wrapper::single, position, db_uint64, "uint64") || not_null_check_failed(*wrapper, position)) { return 0LL; @@ -1514,7 +1514,7 @@ SOCI_DECL double soci_get_into_double(statement_handle st, int position) statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::single, position, dt_double, "double") || + statement_wrapper::single, position, db_double, "double") || not_null_check_failed(*wrapper, position)) { return 0.0; @@ -1528,7 +1528,7 @@ SOCI_DECL char const * soci_get_into_date(statement_handle st, int position) statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::single, position, dt_date, "date") || + statement_wrapper::single, position, db_date, "date") || not_null_check_failed(*wrapper, position)) { return ""; @@ -1544,7 +1544,7 @@ SOCI_DECL blob_handle soci_get_into_blob(statement_handle st, int position) statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::single, position, dt_blob, "blob") || + statement_wrapper::single, position, db_blob, "blob") || not_null_check_failed(*wrapper, position)) { return NULL; @@ -1591,41 +1591,41 @@ SOCI_DECL void soci_into_resize_v(statement_handle st, int new_size) switch (wrapper->into_types[i]) { - case dt_string: + case db_string: wrapper->into_strings_v[i].resize(new_size); break; - case dt_int8: + case db_int8: wrapper->into_int8_v[i].resize(new_size); break; - case dt_uint8: + case db_uint8: wrapper->into_uint8_v[i].resize(new_size); break; - case dt_int16: + case db_int16: wrapper->into_int16_v[i].resize(new_size); break; - case dt_uint16: + case db_uint16: wrapper->into_uint16_v[i].resize(new_size); break; - case dt_int32: + case db_int32: wrapper->into_int32_v[i].resize(new_size); break; - case dt_uint32: + case db_uint32: wrapper->into_uint32_v[i].resize(new_size); break; - case dt_int64: + case db_int64: wrapper->into_int64_v[i].resize(new_size); break; - case dt_uint64: + case db_uint64: wrapper->into_uint64_v[i].resize(new_size); break; - case dt_double: + case db_double: wrapper->into_doubles_v[i].resize(new_size); break; - case dt_date: + case db_date: wrapper->into_dates_v[i].resize(new_size); break; - case dt_blob: - case dt_xml: + case db_blob: + case db_xml: // no support for bulk blob break; } @@ -1659,7 +1659,7 @@ SOCI_DECL char const * soci_get_into_string_v(statement_handle st, int position, statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::bulk, position, dt_string, "string")) + statement_wrapper::bulk, position, db_string, "string")) { return ""; } @@ -1689,7 +1689,7 @@ SOCI_DECL int8_t soci_get_into_int8_v(statement_handle st, int position, int ind statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::bulk, position, dt_int8, "int8")) + statement_wrapper::bulk, position, db_int8, "int8")) { return 0; } @@ -1709,7 +1709,7 @@ SOCI_DECL uint8_t soci_get_into_uint8_v(statement_handle st, int position, int i statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::bulk, position, dt_uint8, "uint8")) + statement_wrapper::bulk, position, db_uint8, "uint8")) { return 0; } @@ -1729,7 +1729,7 @@ SOCI_DECL int16_t soci_get_into_int16_v(statement_handle st, int position, int i statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::bulk, position, dt_int16, "int16")) + statement_wrapper::bulk, position, db_int16, "int16")) { return 0; } @@ -1749,7 +1749,7 @@ SOCI_DECL uint16_t soci_get_into_uint16_v(statement_handle st, int position, int statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::bulk, position, dt_uint16, "uint16")) + statement_wrapper::bulk, position, db_uint16, "uint16")) { return 0; } @@ -1769,7 +1769,7 @@ SOCI_DECL int32_t soci_get_into_int32_v(statement_handle st, int position, int i statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::bulk, position, dt_int32, "int32")) + statement_wrapper::bulk, position, db_int32, "int32")) { return 0; } @@ -1789,7 +1789,7 @@ SOCI_DECL uint32_t soci_get_into_uint32_v(statement_handle st, int position, int statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::bulk, position, dt_uint32, "uint32")) + statement_wrapper::bulk, position, db_uint32, "uint32")) { return 0; } @@ -1809,7 +1809,7 @@ SOCI_DECL int64_t soci_get_into_int64_v(statement_handle st, int position, int i statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::bulk, position, dt_int64, "int64")) + statement_wrapper::bulk, position, db_int64, "int64")) { return 0; } @@ -1829,7 +1829,7 @@ SOCI_DECL uint64_t soci_get_into_uint64_v(statement_handle st, int position, int statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::bulk, position, dt_uint64, "uint64")) + statement_wrapper::bulk, position, db_uint64, "uint64")) { return 0; } @@ -1849,7 +1849,7 @@ SOCI_DECL double soci_get_into_double_v(statement_handle st, int position, int i statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::bulk, position, dt_double, "double")) + statement_wrapper::bulk, position, db_double, "double")) { return 0.0; } @@ -1869,7 +1869,7 @@ SOCI_DECL char const * soci_get_into_date_v(statement_handle st, int position, i statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::bulk, position, dt_date, "date")) + statement_wrapper::bulk, position, db_date, "date")) { return ""; } @@ -2317,7 +2317,7 @@ SOCI_DECL void soci_set_use_string(statement_handle st, char const * name, char statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_string, statement_wrapper::single, "string")) + name, db_string, statement_wrapper::single, "string")) { return; } @@ -2341,7 +2341,7 @@ SOCI_DECL void soci_set_use_int8(statement_handle st, char const * name, int8_t statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_int8, statement_wrapper::single, "int8")) + name, db_int8, statement_wrapper::single, "int8")) { return; } @@ -2355,7 +2355,7 @@ SOCI_DECL void soci_set_use_uint8(statement_handle st, char const * name, uint32 statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_uint32, statement_wrapper::single, "uint32")) + name, db_uint32, statement_wrapper::single, "uint32")) { return; } @@ -2369,7 +2369,7 @@ SOCI_DECL void soci_set_use_int16(statement_handle st, char const * name, int16_ statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_int16, statement_wrapper::single, "int16")) + name, db_int16, statement_wrapper::single, "int16")) { return; } @@ -2383,7 +2383,7 @@ SOCI_DECL void soci_set_use_uint16(statement_handle st, char const * name, uint1 statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_uint16, statement_wrapper::single, "uint16")) + name, db_uint16, statement_wrapper::single, "uint16")) { return; } @@ -2397,7 +2397,7 @@ SOCI_DECL void soci_set_use_int32(statement_handle st, char const * name, int32_ statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_int32, statement_wrapper::single, "int32")) + name, db_int32, statement_wrapper::single, "int32")) { return; } @@ -2411,7 +2411,7 @@ SOCI_DECL void soci_set_use_uint32(statement_handle st, char const * name, uint3 statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_uint32, statement_wrapper::single, "uint32")) + name, db_uint32, statement_wrapper::single, "uint32")) { return; } @@ -2425,7 +2425,7 @@ SOCI_DECL void soci_set_use_int64(statement_handle st, char const * name, int64_ statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_int64, statement_wrapper::single, "int64")) + name, db_int64, statement_wrapper::single, "int64")) { return; } @@ -2439,7 +2439,7 @@ SOCI_DECL void soci_set_use_uint64(statement_handle st, char const * name, uint6 statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_uint64, statement_wrapper::single, "uint64")) + name, db_uint64, statement_wrapper::single, "uint64")) { return; } @@ -2453,7 +2453,7 @@ SOCI_DECL void soci_set_use_double(statement_handle st, char const * name, doubl statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_double, statement_wrapper::single, "double")) + name, db_double, statement_wrapper::single, "double")) { return; } @@ -2467,7 +2467,7 @@ SOCI_DECL void soci_set_use_date(statement_handle st, char const * name, char co statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_date, statement_wrapper::single, "date")) + name, db_date, statement_wrapper::single, "date")) { return; } @@ -2488,7 +2488,7 @@ SOCI_DECL void soci_set_use_blob(statement_handle st, char const * name, blob_ha statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_blob, statement_wrapper::single, "blob")) + name, db_blob, statement_wrapper::single, "blob")) { return; } @@ -2586,7 +2586,7 @@ SOCI_DECL void soci_set_use_string_v(statement_handle st, statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_string, statement_wrapper::bulk, "vector string")) + name, db_string, statement_wrapper::bulk, "vector string")) { return; } @@ -2619,7 +2619,7 @@ SOCI_DECL void soci_set_use_int8_v(statement_handle st, statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_int8, statement_wrapper::bulk, "vector int8")) + name, db_int8, statement_wrapper::bulk, "vector int8")) { return; } @@ -2640,7 +2640,7 @@ SOCI_DECL void soci_set_use_uint8_v(statement_handle st, statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_uint8, statement_wrapper::bulk, "vector uint8")) + name, db_uint8, statement_wrapper::bulk, "vector uint8")) { return; } @@ -2661,7 +2661,7 @@ SOCI_DECL void soci_set_use_int16_v(statement_handle st, statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_int16, statement_wrapper::bulk, "vector int16")) + name, db_int16, statement_wrapper::bulk, "vector int16")) { return; } @@ -2682,7 +2682,7 @@ SOCI_DECL void soci_set_use_uint16_v(statement_handle st, statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_uint16, statement_wrapper::bulk, "vector uint16")) + name, db_uint16, statement_wrapper::bulk, "vector uint16")) { return; } @@ -2703,7 +2703,7 @@ SOCI_DECL void soci_set_use_int32_v(statement_handle st, statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_int32, statement_wrapper::bulk, "vector int32")) + name, db_int32, statement_wrapper::bulk, "vector int32")) { return; } @@ -2724,7 +2724,7 @@ SOCI_DECL void soci_set_use_uint32_v(statement_handle st, statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_uint32, statement_wrapper::bulk, "vector uint32")) + name, db_uint32, statement_wrapper::bulk, "vector uint32")) { return; } @@ -2745,7 +2745,7 @@ SOCI_DECL void soci_set_use_int64_v(statement_handle st, statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_int64, statement_wrapper::bulk, "vector int64")) + name, db_int64, statement_wrapper::bulk, "vector int64")) { return; } @@ -2766,7 +2766,7 @@ SOCI_DECL void soci_set_use_uint64_v(statement_handle st, statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_uint64, statement_wrapper::bulk, "vector uint64")) + name, db_uint64, statement_wrapper::bulk, "vector uint64")) { return; } @@ -2787,7 +2787,7 @@ SOCI_DECL void soci_set_use_double_v(statement_handle st, statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_double, statement_wrapper::bulk, "vector double")) + name, db_double, statement_wrapper::bulk, "vector double")) { return; } @@ -2808,7 +2808,7 @@ SOCI_DECL void soci_set_use_date_v(statement_handle st, statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_date, statement_wrapper::bulk, "vector date")) + name, db_date, statement_wrapper::bulk, "vector date")) { return; } @@ -2852,7 +2852,7 @@ SOCI_DECL char const * soci_get_use_string(statement_handle st, char const * nam statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_string, statement_wrapper::bulk, "string")) + name, db_string, statement_wrapper::bulk, "string")) { return ""; } @@ -2875,7 +2875,7 @@ SOCI_DECL int8_t soci_get_use_int8(statement_handle st, char const * name) statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_int8, statement_wrapper::bulk, "int8")) + name, db_int8, statement_wrapper::bulk, "int8")) { return 0; } @@ -2888,7 +2888,7 @@ SOCI_DECL uint8_t soci_get_use_uint8(statement_handle st, char const * name) statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_uint8, statement_wrapper::bulk, "uint8")) + name, db_uint8, statement_wrapper::bulk, "uint8")) { return 0; } @@ -2901,7 +2901,7 @@ SOCI_DECL int16_t soci_get_use_int16(statement_handle st, char const * name) statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_int16, statement_wrapper::bulk, "int16")) + name, db_int16, statement_wrapper::bulk, "int16")) { return 0; } @@ -2914,7 +2914,7 @@ SOCI_DECL uint16_t soci_get_use_uint16(statement_handle st, char const * name) statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_uint16, statement_wrapper::bulk, "uint16")) + name, db_uint16, statement_wrapper::bulk, "uint16")) { return 0; } @@ -2927,7 +2927,7 @@ SOCI_DECL int32_t soci_get_use_int32(statement_handle st, char const * name) statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_int32, statement_wrapper::bulk, "int32")) + name, db_int32, statement_wrapper::bulk, "int32")) { return 0; } @@ -2940,7 +2940,7 @@ SOCI_DECL uint32_t soci_get_use_uint32(statement_handle st, char const * name) statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_uint32, statement_wrapper::bulk, "uint32")) + name, db_uint32, statement_wrapper::bulk, "uint32")) { return 0; } @@ -2953,7 +2953,7 @@ SOCI_DECL int64_t soci_get_use_int64(statement_handle st, char const * name) statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_int64, statement_wrapper::bulk, "int64")) + name, db_int64, statement_wrapper::bulk, "int64")) { return 0LL; } @@ -2966,7 +2966,7 @@ SOCI_DECL uint64_t soci_get_use_uint64(statement_handle st, char const * name) statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_uint64, statement_wrapper::bulk, "uint64")) + name, db_uint64, statement_wrapper::bulk, "uint64")) { return 0LL; } @@ -2979,7 +2979,7 @@ SOCI_DECL double soci_get_use_double(statement_handle st, char const * name) statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_double, statement_wrapper::bulk, "double")) + name, db_double, statement_wrapper::bulk, "double")) { return 0.0; } @@ -2992,7 +2992,7 @@ SOCI_DECL char const * soci_get_use_date(statement_handle st, char const * name) statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_date, statement_wrapper::bulk, "date")) + name, db_date, statement_wrapper::bulk, "date")) { return ""; } @@ -3011,7 +3011,7 @@ SOCI_DECL blob_handle soci_get_use_blob(statement_handle st, char const * name) statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_blob, statement_wrapper::bulk, "blob")) + name, db_blob, statement_wrapper::bulk, "blob")) { return NULL; } @@ -3036,55 +3036,55 @@ SOCI_DECL void soci_prepare(statement_handle st, char const * query) { switch (wrapper->into_types[i]) { - case dt_string: + case db_string: wrapper->st.exchange( into(wrapper->into_strings[i], wrapper->into_indicators[i])); break; - case dt_int8: + case db_int8: wrapper->st.exchange( into(wrapper->into_int8[i], wrapper->into_indicators[i])); break; - case dt_uint8: + case db_uint8: wrapper->st.exchange( into(wrapper->into_uint8[i], wrapper->into_indicators[i])); break; - case dt_int16: + case db_int16: wrapper->st.exchange( into(wrapper->into_int16[i], wrapper->into_indicators[i])); break; - case dt_uint16: + case db_uint16: wrapper->st.exchange( into(wrapper->into_uint16[i], wrapper->into_indicators[i])); break; - case dt_int32: + case db_int32: wrapper->st.exchange( into(wrapper->into_int32[i], wrapper->into_indicators[i])); break; - case dt_uint32: + case db_uint32: wrapper->st.exchange( into(wrapper->into_uint32[i], wrapper->into_indicators[i])); break; - case dt_int64: + case db_int64: wrapper->st.exchange( into(wrapper->into_int64[i], wrapper->into_indicators[i])); break; - case dt_uint64: + case db_uint64: wrapper->st.exchange( into(wrapper->into_uint64[i], wrapper->into_indicators[i])); break; - case dt_double: + case db_double: wrapper->st.exchange( into(wrapper->into_doubles[i], wrapper->into_indicators[i])); break; - case dt_date: + case db_date: wrapper->st.exchange( into(wrapper->into_dates[i], wrapper->into_indicators[i])); break; - case dt_blob: + case db_blob: wrapper->st.exchange( into(wrapper->into_blob[i]->blob_, wrapper->into_indicators[i])); break; - case dt_xml: + case db_xml: // no support for xml break; } @@ -3097,52 +3097,52 @@ SOCI_DECL void soci_prepare(statement_handle st, char const * query) { switch (wrapper->into_types[i]) { - case dt_string: + case db_string: wrapper->st.exchange( into(wrapper->into_strings_v[i], wrapper->into_indicators_v[i])); break; - case dt_int8: + case db_int8: wrapper->st.exchange( into(wrapper->into_int8_v[i], wrapper->into_indicators_v[i])); break; - case dt_uint8: + case db_uint8: wrapper->st.exchange( into(wrapper->into_uint8_v[i], wrapper->into_indicators_v[i])); break; - case dt_int16: + case db_int16: wrapper->st.exchange( into(wrapper->into_int16_v[i], wrapper->into_indicators_v[i])); break; - case dt_uint16: + case db_uint16: wrapper->st.exchange( into(wrapper->into_uint16_v[i], wrapper->into_indicators_v[i])); break; - case dt_int32: + case db_int32: wrapper->st.exchange( into(wrapper->into_int32_v[i], wrapper->into_indicators_v[i])); break; - case dt_uint32: + case db_uint32: wrapper->st.exchange( into(wrapper->into_uint32_v[i], wrapper->into_indicators_v[i])); break; - case dt_int64: + case db_int64: wrapper->st.exchange( into(wrapper->into_int64_v[i], wrapper->into_indicators_v[i])); break; - case dt_uint64: + case db_uint64: wrapper->st.exchange( into(wrapper->into_uint64_v[i], wrapper->into_indicators_v[i])); break; - case dt_double: + case db_double: wrapper->st.exchange( into(wrapper->into_doubles_v[i], wrapper->into_indicators_v[i])); break; - case dt_date: + case db_date: wrapper->st.exchange( into(wrapper->into_dates_v[i], wrapper->into_indicators_v[i])); break; - case dt_blob: - case dt_xml: + case db_blob: + case db_xml: // no support for bulk blob and xml break; } diff --git a/src/core/statement.cpp b/src/core/statement.cpp index 28b1f55e7..f5a7000f6 100644 --- a/src/core/statement.cpp +++ b/src/core/statement.cpp @@ -630,67 +630,67 @@ namespace details // Map data_types to stock types for dynamic result set support template<> -void statement_impl::bind_into() +void statement_impl::bind_into() { into_row(); } template<> -void statement_impl::bind_into() +void statement_impl::bind_into() { into_row(); } template<> -void statement_impl::bind_into() +void statement_impl::bind_into() { into_row(); } template<> -void statement_impl::bind_into() +void statement_impl::bind_into() { into_row(); } template<> -void statement_impl::bind_into() +void statement_impl::bind_into() { into_row(); } template<> -void statement_impl::bind_into() +void statement_impl::bind_into() { into_row(); } template<> -void statement_impl::bind_into() +void statement_impl::bind_into() { into_row(); } template<> -void statement_impl::bind_into() +void statement_impl::bind_into() { into_row(); } template<> -void statement_impl::bind_into() +void statement_impl::bind_into() { into_row(); } template<> -void statement_impl::bind_into() +void statement_impl::bind_into() { into_row(); } template<> -void statement_impl::bind_into() +void statement_impl::bind_into() { into_row(); } @@ -703,54 +703,52 @@ void statement_impl::describe() for (int i = 1; i <= numcols; ++i) { data_type dtype; + db_type dbtype; std::string columnName; - backEnd_->describe_column(i, dtype, columnName); + backEnd_->describe_column(i, dtype, dbtype, columnName); column_properties props; props.set_name(columnName); props.set_data_type(dtype); + props.set_db_type(dbtype); - switch (dtype) + switch (dbtype) { - case dt_string: - bind_into(); + case db_string: + case db_blob: + case db_xml: + bind_into(); break; - case dt_blob: - bind_into(); + case db_double: + bind_into(); break; - case dt_xml: - bind_into(); + case db_int8: + bind_into(); break; - case dt_double: - bind_into(); + case db_uint8: + bind_into(); break; - case dt_int8: - bind_into(); + case db_int16: + bind_into(); break; - case dt_uint8: - bind_into(); + case db_uint16: + bind_into(); break; - case dt_int16: - bind_into(); + case db_int32: + bind_into(); break; - case dt_uint16: - bind_into(); + case db_uint32: + bind_into(); break; - case dt_int32: - bind_into(); + case db_int64: + bind_into(); break; - case dt_uint32: - bind_into(); + case db_uint64: + bind_into(); break; - case dt_int64: - bind_into(); - break; - case dt_uint64: - bind_into(); - break; - case dt_date: - bind_into(); + case db_date: + bind_into(); break; default: std::ostringstream msg; diff --git a/tests/common-tests.h b/tests/common-tests.h index 305c3971a..714b274ee 100644 --- a/tests/common-tests.h +++ b/tests/common-tests.h @@ -2936,15 +2936,21 @@ TEST_CASE_METHOD(common_tests, "Dynamic row binding", "[core][dynamic]") CHECK(r.size() == 5); CHECK(r.get_properties(0).get_data_type() == dt_double); + CHECK(r.get_properties(0).get_db_type() == db_double); CHECK(r.get_properties(1).get_data_type() == dt_integer); + CHECK(r.get_properties(1).get_db_type() == db_int32); CHECK(r.get_properties(2).get_data_type() == dt_string); + CHECK(r.get_properties(2).get_db_type() == db_string); CHECK(r.get_properties(3).get_data_type() == dt_date); + CHECK(r.get_properties(3).get_db_type() == db_date); // type char is visible as string // - to comply with the implementation for Oracle CHECK(r.get_properties(4).get_data_type() == dt_string); + CHECK(r.get_properties(4).get_db_type() == db_string); CHECK(r.get_properties("NUM_INT").get_data_type() == dt_integer); + CHECK(r.get_properties("NUM_INT").get_db_type() == db_int32); CHECK(r.get_properties(0).get_name() == "NUM_FLOAT"); CHECK(r.get_properties(1).get_name() == "NUM_INT"); @@ -3010,16 +3016,22 @@ TEST_CASE_METHOD(common_tests, "Dynamic row binding", "[core][dynamic]") CHECK(r.size() == 5); CHECK(r.get_properties(0).get_data_type() == dt_double); + CHECK(r.get_properties(0).get_db_type() == db_double); CHECK(r.get_properties(1).get_data_type() == dt_integer); + CHECK(r.get_properties(1).get_db_type() == db_int32); CHECK(r.get_properties(2).get_data_type() == dt_string); + CHECK(r.get_properties(2).get_db_type() == db_string); CHECK(r.get_properties(3).get_data_type() == dt_date); + CHECK(r.get_properties(3).get_db_type() == db_date); sql << "select name, num_int from soci_test", into(r); CHECK(r.size() == 2); CHECK(r.get_properties(0).get_data_type() == dt_string); + CHECK(r.get_properties(0).get_db_type() == db_string); CHECK(r.get_properties(1).get_data_type() == dt_integer); + CHECK(r.get_properties(1).get_db_type() == db_int32); // Check if row object is movable row moved = std::move(r); @@ -3029,7 +3041,9 @@ TEST_CASE_METHOD(common_tests, "Dynamic row binding", "[core][dynamic]") CHECK(r.size() == 0); CHECK(moved.get_properties(0).get_data_type() == dt_string); + CHECK(moved.get_properties(0).get_db_type() == db_string); CHECK(moved.get_properties(1).get_data_type() == dt_integer); + CHECK(moved.get_properties(1).get_db_type() == db_int32); } } @@ -3051,7 +3065,9 @@ TEST_CASE_METHOD(common_tests, "Dynamic row binding 2", "[core][dynamic]") CHECK(r.size() == 1); CHECK(r.get_properties(0).get_data_type() == dt_integer); + CHECK(r.get_properties(0).get_db_type() == db_int32); CHECK(r.get(0) == 20); + CHECK(r.get(0) == 20); } { int id; @@ -3063,19 +3079,25 @@ TEST_CASE_METHOD(common_tests, "Dynamic row binding 2", "[core][dynamic]") st.execute(true); CHECK(r.size() == 1); CHECK(r.get_properties(0).get_data_type() == dt_integer); + CHECK(r.get_properties(0).get_db_type() == db_int32); CHECK(r.get(0) == 20); + CHECK(r.get(0) == 20); id = 3; st.execute(true); CHECK(r.size() == 1); CHECK(r.get_properties(0).get_data_type() == dt_integer); + CHECK(r.get_properties(0).get_db_type() == db_int32); CHECK(r.get(0) == 30); + CHECK(r.get(0) == 30); id = 1; st.execute(true); CHECK(r.size() == 1); CHECK(r.get_properties(0).get_data_type() == dt_integer); + CHECK(r.get_properties(0).get_db_type() == db_int32); CHECK(r.get(0) == 10); + CHECK(r.get(0) == 10); } } @@ -3499,11 +3521,17 @@ TEST_CASE_METHOD(common_tests, "Reading rows from rowset", "[core][row][rowset]" // Properties CHECK(r1.size() == 5); CHECK(r1.get_properties(0).get_data_type() == dt_double); + CHECK(r1.get_properties(0).get_db_type() == db_double); CHECK(r1.get_properties(1).get_data_type() == dt_integer); + CHECK(r1.get_properties(1).get_db_type() == db_int32); CHECK(r1.get_properties(2).get_data_type() == dt_string); + CHECK(r1.get_properties(2).get_db_type() == db_string); CHECK(r1.get_properties(3).get_data_type() == dt_date); + CHECK(r1.get_properties(3).get_db_type() == db_date); CHECK(r1.get_properties(4).get_data_type() == dt_string); + CHECK(r1.get_properties(4).get_db_type() == db_string); CHECK(r1.get_properties("NUM_INT").get_data_type() == dt_integer); + CHECK(r1.get_properties("NUM_INT").get_db_type() == db_int32); // Data @@ -3562,11 +3590,17 @@ TEST_CASE_METHOD(common_tests, "Reading rows from rowset", "[core][row][rowset]" // Properties CHECK(r2.size() == 5); CHECK(r2.get_properties(0).get_data_type() == dt_double); + CHECK(r2.get_properties(0).get_db_type() == db_double); CHECK(r2.get_properties(1).get_data_type() == dt_integer); + CHECK(r2.get_properties(1).get_db_type() == db_int32); CHECK(r2.get_properties(2).get_data_type() == dt_string); + CHECK(r2.get_properties(2).get_db_type() == db_string); CHECK(r2.get_properties(3).get_data_type() == dt_date); + CHECK(r2.get_properties(3).get_db_type() == db_date); CHECK(r2.get_properties(4).get_data_type() == dt_string); + CHECK(r2.get_properties(4).get_db_type() == db_string); CHECK(r2.get_properties("NUM_INT").get_data_type() == dt_integer); + CHECK(r2.get_properties("NUM_INT").get_db_type() == db_int32); std::string newName = r2.get(2); CHECK(name != newName); @@ -3625,10 +3659,15 @@ TEST_CASE_METHOD(common_tests, "Reading rows from rowset", "[core][row][rowset]" // Properties CHECK(r1.size() == 5); CHECK(r1.get_properties(0).get_data_type() == dt_integer); + CHECK(r1.get_properties(0).get_db_type() == db_int32); CHECK(r1.get_properties(1).get_data_type() == dt_double); + CHECK(r1.get_properties(1).get_db_type() == db_double); CHECK(r1.get_properties(2).get_data_type() == dt_string); + CHECK(r1.get_properties(2).get_db_type() == db_string); CHECK(r1.get_properties(3).get_data_type() == dt_date); + CHECK(r1.get_properties(3).get_db_type() == db_date); CHECK(r1.get_properties(4).get_data_type() == dt_string); + CHECK(r1.get_properties(4).get_db_type() == db_string); // Data CHECK(r1.get_indicator(0) == soci::i_ok); @@ -3974,8 +4013,11 @@ TEST_CASE_METHOD(common_tests, "NULL with optional", "[core][boost][null]") // and tests the remaining column only. //CHECK(r1.get_properties(0).get_data_type() == dt_integer); + //CHECK(r1.get_properties(0).get_exchnage_data_type() == db_int32); CHECK(r1.get_properties(1).get_data_type() == dt_integer); + CHECK(r1.get_properties(1).get_db_type() == db_int32); CHECK(r1.get_properties(2).get_data_type() == dt_string); + CHECK(r1.get_properties(2).get_db_type() == db_string); //CHECK(r1.get(0) == 1); CHECK(r1.get(1) == 5); CHECK(r1.get(2) == "abc"); @@ -3991,8 +4033,11 @@ TEST_CASE_METHOD(common_tests, "NULL with optional", "[core][boost][null]") CHECK(r2.size() == 3); // CHECK(r2.get_properties(0).get_data_type() == dt_integer); + // CHECK(r2.get_properties(0).get_db_type() == db_int32); CHECK(r2.get_properties(1).get_data_type() == dt_integer); + CHECK(r2.get_properties(1).get_db_type() == db_int32); CHECK(r2.get_properties(2).get_data_type() == dt_string); + CHECK(r2.get_properties(2).get_db_type() == db_string); //CHECK(r2.get(0) == 2); try { @@ -4447,8 +4492,11 @@ TEST_CASE_METHOD(common_tests, "NULL with std optional", "[core][null]") // and tests the remaining column only. //CHECK(r1.get_properties(0).get_data_type() == dt_integer); + //CHECK(r1.get_properties(0).get_db_type() == db_int32); CHECK(r1.get_properties(1).get_data_type() == dt_integer); + CHECK(r1.get_properties(1).get_db_type() == db_int32); CHECK(r1.get_properties(2).get_data_type() == dt_string); + CHECK(r1.get_properties(2).get_db_type() == db_string); //CHECK(r1.get(0) == 1); CHECK(r1.get(1) == 5); CHECK(r1.get(2) == "abc"); @@ -4464,8 +4512,11 @@ TEST_CASE_METHOD(common_tests, "NULL with std optional", "[core][null]") CHECK(r2.size() == 3); // CHECK(r2.get_properties(0).get_data_type() == dt_integer); + // CHECK(r2.get_properties(0).get_db_type() == db_int32); CHECK(r2.get_properties(1).get_data_type() == dt_integer); + CHECK(r2.get_properties(1).get_db_type() == db_int32); CHECK(r2.get_properties(2).get_data_type() == dt_string); + CHECK(r2.get_properties(2).get_db_type() == db_string); //CHECK(r2.get(0) == 2); try { diff --git a/tests/firebird/test-firebird.cpp b/tests/firebird/test-firebird.cpp index 7c8b58a1c..769ae0d8f 100644 --- a/tests/firebird/test-firebird.cpp +++ b/tests/firebird/test-firebird.cpp @@ -773,8 +773,11 @@ TEST_CASE("Firebird dynamic binding", "[firebird][dynamic]") CHECK(r.get_properties(2).get_name() == "NTEST"); CHECK(r.get_properties(0).get_data_type() == dt_integer); + CHECK(r.get_properties(0).get_db_type() == db_int32); CHECK(r.get_properties(1).get_data_type() == dt_string); + CHECK(r.get_properties(1).get_db_type() == db_string); CHECK(r.get_properties(2).get_data_type() == dt_double); + CHECK(r.get_properties(2).get_db_type() == db_double); // get properties by name CHECK(r.get_properties("ID").get_name() == "ID"); @@ -782,8 +785,11 @@ TEST_CASE("Firebird dynamic binding", "[firebird][dynamic]") CHECK(r.get_properties("NTEST").get_name() == "NTEST"); CHECK(r.get_properties("ID").get_data_type() == dt_integer); + CHECK(r.get_properties("ID").get_db_type() == db_int32); CHECK(r.get_properties("MSG").get_data_type() == dt_string); + CHECK(r.get_properties("MSG").get_db_type() == db_string); CHECK(r.get_properties("NTEST").get_data_type() == dt_double); + CHECK(r.get_properties("NTEST").get_db_type() == db_double); // get values by position CHECK(r.get(0) == 1); @@ -1190,18 +1196,24 @@ TEST_CASE("Firebird decimals as strings", "[firebird][decimal][string]") // get properties by position CHECK(r.get_properties(0).get_name() == "NTEST1"); CHECK(r.get_properties(0).get_data_type() == dt_string); + CHECK(r.get_properties(0).get_db_type() == db_string); CHECK(r.get_properties(1).get_name() == "NTEST2"); CHECK(r.get_properties(1).get_data_type() == dt_string); + CHECK(r.get_properties(1).get_db_type() == db_string); CHECK(r.get_properties(2).get_name() == "NTEST3"); CHECK(r.get_properties(2).get_data_type() == dt_string); + CHECK(r.get_properties(2).get_db_type() == db_string); // get properties by name CHECK(r.get_properties("NTEST1").get_name() == "NTEST1"); CHECK(r.get_properties("NTEST1").get_data_type() == dt_string); + CHECK(r.get_properties("NTEST1").get_db_type() == db_string); CHECK(r.get_properties("NTEST2").get_name() == "NTEST2"); CHECK(r.get_properties("NTEST2").get_data_type() == dt_string); + CHECK(r.get_properties("NTEST2").get_db_type() == db_string); CHECK(r.get_properties("NTEST3").get_name() == "NTEST3"); CHECK(r.get_properties("NTEST3").get_data_type() == dt_string); + CHECK(r.get_properties("NTEST3").get_db_type() == db_string); // get values by position CHECK(r.get(0) == d_str1); diff --git a/tests/mysql/test-mysql.cpp b/tests/mysql/test-mysql.cpp index aed9952fb..7e933432e 100644 --- a/tests/mysql/test-mysql.cpp +++ b/tests/mysql/test-mysql.cpp @@ -450,32 +450,44 @@ TEST_CASE("MySQL text and blob", "[mysql][text][blob]") "from soci_test order by id"); rowset::const_iterator r = rs.begin(); CHECK(r->get_properties(0).get_data_type() == dt_string); + CHECK(r->get_properties(0).get_db_type() == db_string); CHECK(r->get(0) == "foo"); CHECK(r->get_properties(1).get_data_type() == dt_string); + CHECK(r->get_properties(1).get_db_type() == db_string); CHECK(r->get(1) == "bar"); CHECK(r->get_properties(2).get_data_type() == dt_string); + CHECK(r->get_properties(2).get_db_type() == db_string); CHECK(r->get(2) == "baz"); ++r; CHECK(r->get_properties(0).get_data_type() == dt_string); + CHECK(r->get_properties(0).get_db_type() == db_string); CHECK(r->get(0) == std::string("qwerty\0uiop", 11)); CHECK(r->get_properties(1).get_data_type() == dt_string); + CHECK(r->get_properties(1).get_db_type() == db_string); CHECK(r->get(1) == std::string("zxcv\0bnm", 8)); CHECK(r->get_properties(2).get_data_type() == dt_string); + CHECK(r->get_properties(2).get_db_type() == db_string); CHECK(r->get(2) == std::string("qwerty\0uiop\0zxcvbnm\0", 20)); ++r; CHECK(r->get_properties(0).get_data_type() == dt_string); + CHECK(r->get_properties(0).get_db_type() == db_string); CHECK(r->get(0) == a); CHECK(r->get_properties(1).get_data_type() == dt_string); + CHECK(r->get_properties(1).get_db_type() == db_string); CHECK(r->get(1) == b); CHECK(r->get_properties(2).get_data_type() == dt_string); + CHECK(r->get_properties(2).get_db_type() == db_string); CHECK(r->get(2) == c); ++r; CHECK(r->get_properties(0).get_data_type() == dt_string); + CHECK(r->get_properties(0).get_db_type() == db_string); CHECK(r->get(0) == x); CHECK(r->get_properties(1).get_data_type() == dt_string); + CHECK(r->get_properties(1).get_db_type() == db_string); CHECK(r->get(1) == y); CHECK(r->get_properties(2).get_data_type() == dt_string); + CHECK(r->get_properties(2).get_db_type() == db_string); CHECK(r->get(2) == z); ++r; CHECK(r == rs.end()); @@ -688,8 +700,10 @@ TEST_CASE("MySQL tinyint", "[mysql][int][tinyint]") row r; sql << "select val from soci_test", into(r); REQUIRE(r.size() == 1); - CHECK(r.get_properties("val").get_data_type() == dt_uint32); + CHECK(r.get_properties("val").get_data_type() == dt_long_long); + CHECK(r.get_properties("val").get_db_type() == db_uint32); CHECK(r.get("val") == 0xffffff00); + CHECK(r.get("val") == 0xffffff00); } { soci::session sql(backEnd, connectString); @@ -698,7 +712,8 @@ TEST_CASE("MySQL tinyint", "[mysql][int][tinyint]") row r; sql << "select val from soci_test", into(r); REQUIRE(r.size() == 1); - CHECK(r.get_properties("val").get_data_type() == dt_int8); + CHECK(r.get_properties("val").get_data_type() == dt_integer); + CHECK(r.get_properties("val").get_db_type() == db_int8); CHECK(r.get("val") == -123); } { @@ -708,7 +723,8 @@ TEST_CASE("MySQL tinyint", "[mysql][int][tinyint]") row r; sql << "select val from soci_test", into(r); REQUIRE(r.size() == 1); - CHECK(r.get_properties("val").get_data_type() == dt_uint8); + CHECK(r.get_properties("val").get_data_type() == dt_integer); + CHECK(r.get_properties("val").get_db_type() == db_uint8); CHECK(r.get("val") == 123); } { @@ -719,7 +735,9 @@ TEST_CASE("MySQL tinyint", "[mysql][int][tinyint]") sql << "select val from soci_test", into(r); REQUIRE(r.size() == 1); CHECK(r.get_properties("val").get_data_type() == dt_unsigned_long_long); + CHECK(r.get_properties("val").get_db_type() == db_uint64); CHECK(r.get("val") == 123456789012345ULL); + CHECK(r.get("val") == 123456789012345ULL); } { soci::session sql(backEnd, connectString); @@ -729,7 +747,9 @@ TEST_CASE("MySQL tinyint", "[mysql][int][tinyint]") sql << "select val from soci_test", into(r); REQUIRE(r.size() == 1); CHECK(r.get_properties("val").get_data_type() == dt_long_long); + CHECK(r.get_properties("val").get_db_type() == db_int64); CHECK(r.get("val") == -123456789012345LL); + CHECK(r.get("val") == -123456789012345LL); } } @@ -764,6 +784,7 @@ TEST_CASE("MySQL strings", "[mysql][string]") REQUIRE(r.size() == 13); for (int i = 0; i < 13; i++) { CHECK(r.get_properties(i).get_data_type() == dt_string); + CHECK(r.get_properties(i).get_db_type() == db_string); if (i < 6) { CHECK(r.get(i) == text); } else if (i < 12) { diff --git a/tests/postgresql/test-postgresql.cpp b/tests/postgresql/test-postgresql.cpp index a31557924..a69459c49 100644 --- a/tests/postgresql/test-postgresql.cpp +++ b/tests/postgresql/test-postgresql.cpp @@ -637,6 +637,7 @@ TEST_CASE("PostgreSQL bytea", "[postgresql][bytea]") REQUIRE(r.size() == 1); column_properties const& props = r.get_properties(0); CHECK(props.get_data_type() == soci::dt_string); + CHECK(props.get_db_type() == soci::db_string); std::string bin2 = r.get(0); CHECK(bin2 == expectedBytea); } @@ -786,12 +787,14 @@ TEST_CASE("PostgreSQL DDL with metadata", "[postgresql][ddl]") if (ci.name == "i") { CHECK(ci.type == soci::dt_integer); + CHECK(ci.dataType == soci::db_int32); CHECK(ci.nullable); i_found = true; } else if (ci.name == "j") { CHECK(ci.type == soci::dt_integer); + CHECK(ci.dataType == soci::db_int32); CHECK(ci.nullable); j_found = true; } @@ -864,18 +867,21 @@ TEST_CASE("PostgreSQL DDL with metadata", "[postgresql][ddl]") if (ci.name == "j") { CHECK(ci.type == soci::dt_integer); + CHECK(ci.dataType == soci::db_int32); CHECK(ci.nullable); j_found = true; } else if (ci.name == "k") { CHECK(ci.type == soci::dt_integer); + CHECK(ci.dataType == soci::db_int32); CHECK(ci.nullable); k_found = true; } else if (ci.name == "big") { CHECK(ci.type == soci::dt_string); + CHECK(ci.dataType == soci::db_string); CHECK(ci.precision == 0); // "unlimited" for strings big_found = true; } @@ -905,24 +911,28 @@ TEST_CASE("PostgreSQL DDL with metadata", "[postgresql][ddl]") if (ci.name == "i") { CHECK(ci.type == soci::dt_integer); + CHECK(ci.dataType == soci::db_int32); CHECK(ci.nullable); i_found = true; } else if (ci.name == "j") { CHECK(ci.type == soci::dt_integer); + CHECK(ci.dataType == soci::db_int32); CHECK(ci.nullable == false); // primary key j_found = true; } else if (ci.name == "k") { CHECK(ci.type == soci::dt_integer); + CHECK(ci.dataType == soci::db_int32); CHECK(ci.nullable == false); k_found = true; } else if (ci.name == "m") { CHECK(ci.type == soci::dt_integer); + CHECK(ci.dataType == soci::db_int32); CHECK(ci.nullable == false); m_found = true; } From 037a332ca788781f2ab896c6d7a239382e9eba1d Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Wed, 18 Oct 2023 20:58:22 +0200 Subject: [PATCH 37/46] Add db_type description to docs --- docs/api/backend.md | 39 ++++++++++++---------- docs/api/client.md | 14 +++++--- docs/backends/firebird.md | 19 ++++++++--- docs/backends/mysql.md | 40 ++++++++++++++--------- docs/backends/odbc.md | 27 +++++++++------ docs/backends/oracle.md | 22 +++++++++---- docs/backends/postgresql.md | 29 +++++++++++------ docs/backends/sqlite3.md | 29 +++++++++++------ docs/types.md | 65 ++++++++++++++++++++----------------- docs/utilities.md | 20 ++++++------ 10 files changed, 187 insertions(+), 117 deletions(-) diff --git a/docs/api/backend.md b/docs/api/backend.md index aa1066164..372ceca9b 100644 --- a/docs/api/backend.md +++ b/docs/api/backend.md @@ -21,22 +21,25 @@ All names are defined in either `soci` or `soci::details` namespace. // data types, as seen by the user enum data_type { - dt_string, - dt_int8, - dt_uint8, - dt_int16, - dt_uint16, - dt_int32, - dt_integer = dt_int32, - dt_uint32, - dt_int64, - dt_long_long = dt_int64, - dt_uint64, - dt_unsigned_long_long = dt_uint64, - dt_double, - dt_date, - dt_blob, - dt_xml + dt_string, dt_date, dt_double, dt_integer, dt_long_long, dt_unsigned_long_long +}; + +// 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 }; // the enum type for indicator variables @@ -86,8 +89,9 @@ public: }; ``` -The `data_type` enumeration type defines all types that form the core type support for SOCI. +The `data_type` and `db_type` enumeration type defines all types that form the core type support for SOCI. The enum itself can be used by clients when dealing with dynamic rowset description. +`data_type` is deprecated in favor of `db_type`, so users are encouraged to use the latter. The `indicator` enumeration type defines all recognized *states* of data. The `i_truncated` state is provided for the case where the string is retrieved from the database @@ -217,6 +221,7 @@ public: virtual int prepare_for_describe() = 0; virtual void describe_column(int colNum, data_type& dtype, + db_type& dbtype, std::string& column_name) = 0; virtual standard_into_type_backend* make_into_type_backend() = 0; diff --git a/docs/api/client.md b/docs/api/client.md index febfdf9e2..386497ec5 100644 --- a/docs/api/client.md +++ b/docs/api/client.md @@ -13,7 +13,10 @@ The following types are commonly used in the rest of the interface: ```cpp // data types, as seen by the user -enum data_type { dt_string, dt_date, dt_double, dt_int8, dt_uint8, dt_int16, dt_uint16, dt_int32, dt_uint32, dt_int64, dt_uint64 }; +enum data_type { dt_string, dt_date, dt_double, dt_integer, dt_long_long, dt_unsigned_long_long }; + +// data types, as seen by the user +enum db_type { db_string, db_date, db_double, db_int8, db_uint8, db_int16, db_uint16, db_int32, db_uint32, db_int64, db_uint64 }; // the enum type for indicator variables enum indicator { i_ok, i_null, i_truncated }; @@ -22,7 +25,8 @@ enum indicator { i_ok, i_null, i_truncated }; class soci_error : public std::runtime_error { /* ... */ }; ``` -The `data_type` type defines the basic SOCI data types. User provided data types need to be associated with one of these basic types. +The `data_type` and `db_type` types define the basic SOCI data types. User provided data types need to be associated with one of these basic types. +`data_type` is deprecated in favor of `db_type`, so users are encouraged to use the latter. The `indicator` type defines the possible states of data. @@ -443,14 +447,16 @@ class column_properties { public: std::string get_name() const; - data_type get_data_type() const; + data_type_type get_data_type() const; + db_type get_db_type() const; }; ``` This class contains the following members: * `get_name` function that returns the name of the column. -* `get_data_type` that returns the type of the column. +* `get_data_type` that returns the type of the column (deprecate in favor of `get_db_type`). +* `get_db_type` that returns the type of the column. See [Dynamic resultset binding](../types.md#dynamic-binding) for examples. diff --git a/docs/backends/firebird.md b/docs/backends/firebird.md index ddb302463..c4a61d79e 100644 --- a/docs/backends/firebird.md +++ b/docs/backends/firebird.md @@ -73,17 +73,26 @@ type is not known at compile time. When calling `row::get()`, the type you should pass as T depends upon the underlying database type. For the Firebird backend, this type mapping is: -| Firebird Data Type | SOCI Data Type | `row::get` specializations | +| Firebird Data Type | SOCI Data Type (`data_type`) | `row::get` specializations | | --------------------------------------- | --------------------------------------- | --------------------------------- | | numeric, decimal (where scale > 0) | dt_double | double | -| numeric, decimal [^1] (where scale = 0) | dt_int16/dt_int32/dt_int64, dt_double | dt_int16/int32_t/dt_int64, double | +| numeric, decimal [^1] (where scale = 0) | dt_integer, dt_double | int, double | | double precision, float | dt_double | double | -| smallint | dt_int16 | int16_t | -| integer | dt_int32 | int32_t | -| bigint | dt_int64 | int64_t | +| smallint, integer | dt_integer | int | | char, varchar | dt_string | std::string | | date, time, timestamp | dt_date | std::tm | +| Firebird Data Type | SOCI Data Type (`db_type`) | `row::get` specializations | +| --------------------------------------- | --------------------------------------- | --------------------------------- | +| numeric, decimal (where scale > 0) | db_double | double | +| numeric, decimal [^1] (where scale = 0) | db_int16/db_int32/db_int64, db_double | int16_t/int32_t/int64_t, double | +| double precision, float | db_double | double | +| smallint | db_int16 | int16_t | +| integer | db_int32 | int32_t | +| bigint | db_int64 | int64_t | +| char, varchar | db_string | std::string | +| date, time, timestamp | db_date | std::tm | + [^1] There is also 64bit integer type for larger values which is currently not supported. diff --git a/docs/backends/mysql.md b/docs/backends/mysql.md index c89de9be2..bbac99763 100644 --- a/docs/backends/mysql.md +++ b/docs/backends/mysql.md @@ -72,21 +72,31 @@ The MySQL backend supports the use of the SOCI `row` class, which facilitates re When calling `row::get()`, the type you should pass as `T` depends upon the underlying database type. For the MySQL backend, this type mapping is: -| MySQL Data Type | SOCI Data Type | `row::get` specializations | -| ----------------------------------------------------------------------------------------------------------------- | --------------------- | ----------------------------- | -| FLOAT, DOUBLE, DECIMAL and synonyms | dt_double | double | -| TINYINT | dt_int8 | int8_t | -| TINYINT UNSIGNED | dt_uint8 | uint8_t | -| SMALLINT | dt_int16 | int16_t | -| SMALLINT UNSIGNED | dt_uint16 | uint16_t | -| MEDIUMINT | dt_int32 | int32_t | -| MEDIUMINT UNSIGNED | dt_uint32 | uint32_t | -| INT | dt_int32 | int32_t | -| INT UNSIGNED | dt_uint32 | uint32_t | -| BIGINT | dt_int64 | int64_t | -| BIGINT UNSIGNED | dt_uint64 | uint64_t | -| CHAR, VARCHAR, BINARY, VARBINARY, TINYBLOB, MEDIUMBLOB, BLOB,LONGBLOB, TINYTEXT, MEDIUMTEXT, TEXT, LONGTEXT, ENUM | dt_string | std::string | -| TIMESTAMP (works only with MySQL >= 5.0), DATE, TIME, DATETIME | dt_date | std::tm | +| MySQL Data Type | SOCI Data Type (`data_type`) | `row::get` specializations | +| ----------------------------------------------------------------------------------------------------------------- | ---------------------------- | ----------------------------- | +| FLOAT, DOUBLE, DECIMAL and synonyms | dt_double | double | +| TINYINT, TINYINT UNSIGNED, SMALLINT, SMALLINT UNSIGNED, INT | dt_integer | int | +| INT UNSIGNED | dt_long_long | long long or unsigned | +| BIGINT | dt_long_long | long long | +| BIGINT UNSIGNED | dt_unsigned_long_long | unsigned long long | +| CHAR, VARCHAR, BINARY, VARBINARY, TINYBLOB, MEDIUMBLOB, BLOB,LONGBLOB, TINYTEXT, MEDIUMTEXT, TEXT, LONGTEXT, ENUM | dt_string | std::string | +| TIMESTAMP (works only with MySQL >= 5.0), DATE, TIME, DATETIME | dt_date | std::tm | + +| MySQL Data Type | SOCI Data Type (`db_type`) | `row::get` specializations | +| ----------------------------------------------------------------------------------------------------------------- | ---------------------------- | ----------------------------- | +| FLOAT, DOUBLE, DECIMAL and synonyms | db_double | double | +| TINYINT | db_int8 | int8_t | +| TINYINT UNSIGNED | db_uint8 | uint8_t | +| SMALLINT | db_int16 | int16_t | +| SMALLINT UNSIGNED | db_uint16 | uint16_t | +| MEDIUMINT | db_int32 | int32_t | +| MEDIUMINT UNSIGNED | db_uint32 | uint32_t | +| INT | db_int32 | int32_t | +| INT UNSIGNED | db_uint32 | uint32_t | +| BIGINT | db_int64 | int64_t | +| BIGINT UNSIGNED | db_uint64 | uint64_t | +| CHAR, VARCHAR, BINARY, VARBINARY, TINYBLOB, MEDIUMBLOB, BLOB,LONGBLOB, TINYTEXT, MEDIUMTEXT, TEXT, LONGTEXT, ENUM | db_string | std::string | +| TIMESTAMP (works only with MySQL >= 5.0), DATE, TIME, DATETIME | db_date | std::tm | (See the [dynamic resultset binding](../types.md#dynamic-binding) documentation for general information on using the `Row` class.) diff --git a/docs/backends/odbc.md b/docs/backends/odbc.md index 13f9e46df..9365c0281 100644 --- a/docs/backends/odbc.md +++ b/docs/backends/odbc.md @@ -60,18 +60,25 @@ The ODBC backend supports the use of the SOCI `row` class, which facilitates ret When calling `row::get()`, the type you should pass as T depends upon the underlying database type. For the ODBC backend, this type mapping is: -| ODBC Data Type | SOCI Data Type | `row::get` specializations | -| --------------------------------------------------------- | -------------- | ----------------------------- | -| SQL_DOUBLE, SQL_DECIMAL, SQL_REAL, SQL_FLOAT, SQL_NUMERIC | dt_double | double | -| SQL_TINYINT | dt_int8 | int8_t | -| SQL_SMALLINT | dt_int16 | int16_t | -| SQL_INTEGER | dt_int32 | int32_t | -| SQL_BIGINT | dt_int64 | int64_t | -| SQL_CHAR, SQL_VARCHAR | dt_string | std::string | -| SQL_TYPE_DATE, SQL_TYPE_TIME, SQL_TYPE_TIMESTAMP | dt_date | std::tm | +| ODBC Data Type | SOCI Data Type (`data_type`) | `row::get` specializations | +| --------------------------------------------------------- | ---------------------------- | ----------------------------- | +| SQL_DOUBLE, SQL_DECIMAL, SQL_REAL, SQL_FLOAT, SQL_NUMERIC | dt_double | double | +| SQL_TINYINT, SQL_SMALLINT, SQL_INTEGER, SQL_BIGINT | dt_integer | int | +| SQL_CHAR, SQL_VARCHAR | dt_string | std::string | +| SQL_TYPE_DATE, SQL_TYPE_TIME, SQL_TYPE_TIMESTAMP | dt_date | std::tm | + +| ODBC Data Type | SOCI Data Type (`db_type`) | `row::get` specializations | +| --------------------------------------------------------- | -------------------------- | ----------------------------- | +| SQL_DOUBLE, SQL_DECIMAL, SQL_REAL, SQL_FLOAT, SQL_NUMERIC | db_double | double | +| SQL_TINYINT | db_int8 | int8_t | +| SQL_SMALLINT | db_int16 | int16_t | +| SQL_INTEGER | db_int32 | int32_t | +| SQL_BIGINT | db_int64 | int64_t | +| SQL_CHAR, SQL_VARCHAR | db_string | std::string | +| SQL_TYPE_DATE, SQL_TYPE_TIME, SQL_TYPE_TIMESTAMP | db_date | std::tm | Not all ODBC drivers support all datatypes. -Columns having the attribute `unsigned` get mapped to their corresponding `dt_uint[n]` and `uint[n]_t` types. +Columns having the attribute `unsigned` get mapped to their corresponding `db_uint[n]` and `uint[n]_t` types. (See the [dynamic resultset binding](../types.md#dynamic-binding) documentation for general information on using the `row` class.) diff --git a/docs/backends/oracle.md b/docs/backends/oracle.md index 7eeec47c6..13317a6b9 100644 --- a/docs/backends/oracle.md +++ b/docs/backends/oracle.md @@ -71,13 +71,21 @@ The Oracle backend supports the use of the SOCI `row` class, which facilitates r When calling `row::get()`, the type you should pass as `T` depends upon the underlying database type. For the Oracle backend, this type mapping is: -| Oracle Data Type | SOCI Data Type | `row::get` specializations | -| --------------------------------------------------------------------------------- | -------------- | ----------------------------- | -| number (where scale > 0) | dt_double | double | -| number (where scale = 0 and precision ≤ `std::numeric_limits::digits10`) | dt_int32 | int32_t | -| number (where scale = 0) | dt_int64 | int64_t | -| char, varchar, varchar2 | dt_string | std::string | -| date | dt_date | std::tm | +| Oracle Data Type | SOCI Data Type (`data_type`) | `row::get` specializations | +| --------------------------------------------------------------------------------- | ---------------------------- | ----------------------------- | +| number (where scale > 0) | dt_double | double | +| number (where scale = 0 and precision ≤ `std::numeric_limits::digits10`) | dt_integer | int | +| number (where scale = 0) | dt_long_long | long long | +| char, varchar, varchar2 | dt_string | std::string | +| date | dt_date | std::tm | + +| Oracle Data Type | SOCI Data Type (`db_type`) | `row::get` specializations | +| --------------------------------------------------------------------------------- | ---------------------------- | ----------------------------- | +| number (where scale > 0) | db_double | double | +| number (where scale = 0 and precision ≤ `std::numeric_limits::digits10`) | db_int32 | int32_t | +| number (where scale = 0) | db_int64 | int64_t | +| char, varchar, varchar2 | db_string | std::string | +| date | db_date | std::tm | (See the [dynamic resultset binding](../types.md#dynamic-binding) documentation for general information on using the `row` class.) diff --git a/docs/backends/postgresql.md b/docs/backends/postgresql.md index ce3519138..f7268ac32 100644 --- a/docs/backends/postgresql.md +++ b/docs/backends/postgresql.md @@ -88,16 +88,25 @@ The PostgreSQL backend supports the use of the SOCI `row` class, which facilitat When calling `row::get()`, the type you should pass as `T` depends upon the underlying database type. For the PostgreSQL backend, this type mapping is: -| PostgreSQL Data Type | SOCI Data Type | `row::get` specializations | -| ------------------------------------------------------------ | -------------- | ----------------------------- | -| numeric, real, double | dt_double | double | -| boolean | dt_int8 | int8_t | -| smallint | dt_int16 | int16_t | -| integer | dt_int32 | int32_t | -| int8 | dt_int64 | int64_t | -| oid | dt_int32 | int32_t | -| char, varchar, text, cstring, bpchar | dt_string | std::string | -| abstime, reltime, date, time, timestamp, timestamptz, timetz | dt_date | std::tm | +| PostgreSQL Data Type | SOCI Data Type (`data_type`) | `row::get` specializations | +| ------------------------------------------------------------ | ---------------------------- | ----------------------------- | +| numeric, real, double | dt_double | double | +| boolean, smallint, integer | dt_integer | int | +| int8 | dt_long_long | long long | +| oid | dt_integer | unsigned long | +| char, varchar, text, cstring, bpchar | dt_string | std::string | +| abstime, reltime, date, time, timestamp, timestamptz, timetz | dt_date | std::tm | + +| PostgreSQL Data Type | SOCI Data Type (`db_type`) | `row::get` specializations | +| ------------------------------------------------------------ | ---------------------------- | ----------------------------- | +| numeric, real, double | db_double | double | +| boolean | db_int8 | int8_t | +| smallint | db_int16 | int16_t | +| integer | db_int32 | int32_t | +| int8 | db_int64 | int64_t | +| oid | db_int32 | int32_t | +| char, varchar, text, cstring, bpchar | db_string | std::string | +| abstime, reltime, date, time, timestamp, timestamptz, timetz | db_date | std::tm | (See the [dynamic resultset binding](../types.md#dynamic-binding) documentation for general information on using the `row` class.) diff --git a/docs/backends/sqlite3.md b/docs/backends/sqlite3.md index a7df2ea44..a77a7f2a5 100644 --- a/docs/backends/sqlite3.md +++ b/docs/backends/sqlite3.md @@ -75,16 +75,25 @@ When calling `row::get()`, the type you should pass as T depends upon the und For the SQLite3 backend, this type mapping is complicated by the fact the SQLite3 does not enforce [types][INTEGER_PRIMARY_KEY] and makes no attempt to validate the type names used in table creation or alteration statements. SQLite3 will return the type as a string, SOCI will recognize the following strings and match them the corresponding SOCI types: -| SQLite3 Data Type | SOCI Data Type | `row::get` specializations | -| ------------------------------------------------------------------------------------------------------------ | -------------- | ----------------------------- | -| *float*, *decimal*, *double*, *double precision*, *number*, *numeric*, *real* | dt_double | double | -| *tinyint* | dt_int8 | int8_t | -| *smallint* | dt_int16 | int16_t | -| *int*, *integer*, *int2*, *mediumint*, *boolean* | dt_int32 | int32_t | -| *int8*, *bigint* | dt_int64 | int64_t | -| *unsigned big int* | dt_uint64 | uint64_t | -| *text*, *char*, *character*, *clob*, *native character*, *nchar*, *nvarchar*, *varchar*, *varying character* | dt_string | std::string | -| *date*, *time*, *datetime* | dt_date | std::tm | +| SQLite3 Data Type | SOCI Data Type (`data_type`) | `row::get` specializations | +| ------------------------------------------------------------------------------------------------------------ | ---------------------------- | ----------------------------- | +| *float*, *decimal*, *double*, *double precision*, *number*, *numeric*, *real* | dt_double | double | +| *int*, *integer*, *int2*, *mediumint*, *boolean* | dt_integer | int | +| *int8*, *bigint* | dt_long_long | long long | +| *unsigned big int* | dt_unsigned_long_long | unsigned long long | +| *text*, *char*, *character*, *clob*, *native character*, *nchar*, *nvarchar*, *varchar*, *varying character* | dt_string | std::string | +| *date*, *time*, *datetime* | dt_date | std::tm | + +| SQLite3 Data Type | SOCI Data Type (`db_type`) | `row::get` specializations | +| ------------------------------------------------------------------------------------------------------------ | ---------------------------- | ----------------------------- | +| *float*, *decimal*, *double*, *double precision*, *number*, *numeric*, *real* | db_double | double | +| *tinyint* | db_int8 | int8_t | +| *smallint* | db_int16 | int16_t | +| *int*, *integer*, *int2*, *mediumint*, *boolean* | db_int32 | int32_t | +| *int8*, *bigint* | db_int64 | int64_t | +| *unsigned big int* | db_uint64 | uint64_t | +| *text*, *char*, *character*, *clob*, *native character*, *nchar*, *nvarchar*, *varchar*, *varying character* | db_string | std::string | +| *date*, *time*, *datetime* | db_date | std::tm | [INTEGER_PRIMARY_KEY] : There is one case where SQLite3 enforces type. If a column is declared as "integer primary key", then SQLite3 uses that as an alias to the internal ROWID column that exists for every table. Only integers are allowed in this column. diff --git a/docs/types.md b/docs/types.md index e571049d5..e71962611 100644 --- a/docs/types.md +++ b/docs/types.md @@ -64,39 +64,39 @@ for(std::size_t i = 0; i != r.size(); ++i) doc << '<' << props.get_name() << '>'; - switch(props.get_data_type()) + switch(props.get_db_type()) { - case dt_string: + case db_string: doc << r.get(i); break; - case dt_double: + case db_double: doc << r.get(i); break; - case dt_int8: + case db_int8: doc << r.get(i); break; - case dt_uint8: + case db_uint8: doc << r.get(i); break; - case dt_int16: + case db_int16: doc << r.get(i); break; - case dt_uint16: + case db_uint16: doc << r.get(i); break; - case dt_int32: + case db_int32: doc << r.get(i); break; - case dt_uint32: + case db_uint32: doc << r.get(i); break; - case dt_int64: + case db_int64: doc << r.get(i); break; - case dt_uint64: + case db_uint64: doc << r.get(i); break; - case dt_date: + case db_date: std::tm when = r.get(i); doc << asctime(&when); break; @@ -107,26 +107,33 @@ for(std::size_t i = 0; i != r.size(); ++i) doc << ""; ``` -The type `T` parameter that should be passed to `row::get()` depends on the SOCI data type that is returned from `column_properties::get_data_type()`. +The type `T` parameter that should be passed to `row::get()` depends on the SOCI data type that is returned from `data_type column_properties::get_data_type()` or `db_type column_properties::get_db_type()`. +Users are encouraged to use the latter as it supports a wider range of numerical C++ types. `row::get()` throws an exception of type `std::bad_cast` if an incorrect type `T` is requested. -| SOCI Data Type | `row::get` specialization | -|-------------------------|------------------------------| -| `dt_double` | `double` | -| `dt_int8` | `int8_t` | -| `dt_uint8` | `uint8_t` | -| `dt_int16` | `int16_t` | -| `dt_uint16` | `uint16_t` | -| `dt_int32` | `int32_t` | -| `dt_integer` | `int32_t` | -| `dt_uint32` | `uint32_t` | -| `dt_int64` | `int64_t` | -| `dt_long_long` | `int64_t` | -| `dt_uint64` | `uint64_t` | -| `dt_unsigned_long_long` | `uint64_t` | -| `dt_string` | `std::string` | -| `dt_date` | `std::tm` | +| SOCI Data Type (`data_type`) | `row::get` specialization | +|------------------------------|------------------------------| +| `dt_double` | `double` | +| `dt_integer` | `int` | +| `dt_long_long` | `long long` | +| `dt_unsigned_long_long` | `unsigned long long` | +| `dt_string` | `std::string` | +| `dt_date` | `std::tm` | + +| SOCI Data Type (`db_type`) | `row::get` specialization | +|------------------------------|------------------------------| +| `db_double` | `double` | +| `db_int8` | `int8_t` | +| `db_uint8` | `uint8_t` | +| `db_int16` | `int16_t` | +| `db_uint16` | `uint16_t` | +| `db_int32` | `int32_t` | +| `db_uint32` | `uint32_t` | +| `db_int64` | `int64_t` | +| `db_uint64` | `uint64_t` | +| `db_string` | `std::string` | +| `db_date` | `std::tm` | The mapping of underlying database column types to SOCI datatypes is database specific. See the [backend documentation](backends/index.md) for details. diff --git a/docs/utilities.md b/docs/utilities.md index 110f0e19b..4a331dbc0 100644 --- a/docs/utilities.md +++ b/docs/utilities.md @@ -9,7 +9,7 @@ SOCI supports some basic methods to construct portable DDL queries. That is, ins It is possible to create a new table in a single statement: ```cpp -sql.create_table("t1").column("i", soci::dt_integer).column("j", soci::dt_integer); +sql.create_table("t1").column("i", soci::db_int32).column("j", soci::db_int32); ``` Above, table "t1" will be created with two columns ("i", "j") of type integer. @@ -19,9 +19,9 @@ It is also possible to build similar statements piece by piece, which is useful ```cpp { soci::ddl_type ddl = sql.create_table("t2"); - ddl.column("i", soci::dt_integer); - ddl.column("j", soci::dt_integer); - ddl.column("k", soci::dt_integer)("not null"); + ddl.column("i", soci::db_int32); + ddl.column("j", soci::db_int32); + ddl.column("k", soci::db_int32)("not null"); ddl.primary_key("t2_pk", "j"); } ``` @@ -31,9 +31,9 @@ The actual statement is executed at the end of above block, when the ddl object Columns can be added to and dropped from already existing tables as well: ```cpp -sql.add_column("t1", "k", soci::dt_integer); +sql.add_column("t1", "k", soci::db_int32); // or with constraint: -//sql.add_column("t1", "k", soci::dt_integer)("not null"); +//sql.add_column("t1", "k", soci::db_int32)("not null"); sql.drop_column("t1", "i"); ``` @@ -41,8 +41,8 @@ sql.drop_column("t1", "i"); If needed, precision and scale can be defined with additional integer arguments to functions that create columns: ```cpp -sql.add_column("t1", "s", soci::dt_string, precision); -sql.add_column("t1", "d", soci::dt_double, precision, scale); +sql.add_column("t1", "s", soci::db_string, precision); +sql.add_column("t1", "d", soci::db_double, precision, scale); ``` Tables with foreign keys to each other can be also created: @@ -50,8 +50,8 @@ Tables with foreign keys to each other can be also created: ```cpp { soci::ddl_type ddl = sql.create_table("t3"); - ddl.column("x", soci::dt_integer); - ddl.column("y", soci::dt_integer); + ddl.column("x", soci::db_int32); + ddl.column("y", soci::db_int32); ddl.foreign_key("t3_fk", "x", "t2", "j"); } ``` From 06b68c2d00cf3ebd68261c8b3035c9a3ee0c83d8 Mon Sep 17 00:00:00 2001 From: Lukas Zanner Date: Wed, 18 Oct 2023 21:13:51 +0200 Subject: [PATCH 38/46] Forward create_column_type() to db_type overload --- include/soci/soci-backend.h | 41 ++++++++----------------------------- 1 file changed, 9 insertions(+), 32 deletions(-) diff --git a/include/soci/soci-backend.h b/include/soci/soci-backend.h index 494aff669..72f058835 100644 --- a/include/soci/soci-backend.h +++ b/include/soci/soci-backend.h @@ -357,58 +357,35 @@ class session_backend switch (dt) { case dt_string: - { - std::ostringstream oss; - - if (precision == 0) - { - oss << "text"; - } - else - { - oss << "varchar(" << precision << ")"; - } - - res += oss.str(); - } + res += create_column_type(db_string, precision, scale); break; case dt_date: - res += "timestamp"; + res += create_column_type(db_date, precision, scale); break; case dt_double: - { - std::ostringstream oss; - if (precision == 0) - { - oss << "numeric"; - } - else - { - oss << "numeric(" << precision << ", " << scale << ")"; - } - - res += oss.str(); - } + res += create_column_type(db_double, precision, scale); break; case dt_integer: - res += "integer"; + res += create_column_type(db_int32, precision, scale); break; case dt_long_long: - res += "bigint"; + res += create_column_type(db_int64, precision, scale); break; case dt_unsigned_long_long: + res += create_column_type(db_uint64, precision, scale); + break; case dt_blob: - res += "oid"; + res += create_column_type(db_blob, precision, scale); break; case dt_xml: - res += "xml"; + res += create_column_type(db_xml, precision, scale); break; default: From cd738b0af8bdbf06d2824ac463980eea0d40cdec Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 2 Jan 2024 23:45:46 +0100 Subject: [PATCH 39/46] Document db_type first, then data_types Make sure to list db_type first, before the now deprecated data_type. --- docs/api/client.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/api/client.md b/docs/api/client.md index 386497ec5..b034709b1 100644 --- a/docs/api/client.md +++ b/docs/api/client.md @@ -12,12 +12,12 @@ Types related to the backend interface are named here. The following types are commonly used in the rest of the interface: ```cpp -// data types, as seen by the user -enum data_type { dt_string, dt_date, dt_double, dt_integer, dt_long_long, dt_unsigned_long_long }; - // data types, as seen by the user enum db_type { db_string, db_date, db_double, db_int8, db_uint8, db_int16, db_uint16, db_int32, db_uint32, db_int64, db_uint64 }; +// deprecated data types enum which may be still used but is less precise than db_type +enum data_type { dt_string, dt_date, dt_double, dt_integer, dt_long_long, dt_unsigned_long_long }; + // the enum type for indicator variables enum indicator { i_ok, i_null, i_truncated }; @@ -25,8 +25,8 @@ enum indicator { i_ok, i_null, i_truncated }; class soci_error : public std::runtime_error { /* ... */ }; ``` -The `data_type` and `db_type` types define the basic SOCI data types. User provided data types need to be associated with one of these basic types. -`data_type` is deprecated in favor of `db_type`, so users are encouraged to use the latter. +`db_type` defines the basic SOCI data types. User provided data types need to be associated with one of these basic types. +`data_type` is deprecated in favor of `db_type`, please don't use it in the new code any longer. The `indicator` type defines the possible states of data. @@ -447,16 +447,16 @@ class column_properties { public: std::string get_name() const; - data_type_type get_data_type() const; db_type get_db_type() const; + data_type_type get_data_type() const; }; ``` This class contains the following members: * `get_name` function that returns the name of the column. -* `get_data_type` that returns the type of the column (deprecate in favor of `get_db_type`). * `get_db_type` that returns the type of the column. +* `get_data_type` that returns the type of the column (deprecated in favor of `get_db_type`). See [Dynamic resultset binding](../types.md#dynamic-binding) for examples. From a25e605ce2ac219fe9e7b1d29eec1d6fd647fdc8 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 2 Jan 2024 23:49:17 +0100 Subject: [PATCH 40/46] Define newer db_type before deprecated data_type Also define deprecated x_typename synonyms at the end of exchange_type enum. No real changes. --- include/soci/soci-backend.h | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/include/soci/soci-backend.h b/include/soci/soci-backend.h index 72f058835..0d9c18fd4 100644 --- a/include/soci/soci-backend.h +++ b/include/soci/soci-backend.h @@ -19,20 +19,6 @@ namespace soci { -// DEPRECATED. USE db_type INSTEAD. -// data types, as seen by the user -enum data_type -{ - dt_string, - dt_integer, - dt_long_long, - dt_unsigned_long_long, - dt_double, - dt_date, - dt_blob, - dt_xml -}; - // data types, as seen by the user enum db_type { @@ -51,6 +37,13 @@ enum db_type 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 }; @@ -68,15 +61,11 @@ enum exchange_type x_int8, x_uint8, x_int16, - x_short = x_int16, x_uint16, x_int32, - x_integer = x_int32, x_uint32, x_int64, - x_long_long = x_int64, x_uint64, - x_unsigned_long_long = x_uint64, x_double, x_stdtm, x_statement, @@ -84,7 +73,13 @@ enum exchange_type x_blob, x_xmltype, - x_longstring + 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) From 44ef89c38ab3d52de23dee033f126507332d9b0e Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 3 Jan 2024 00:14:20 +0100 Subject: [PATCH 41/46] Don't duplicate code in functions taking data_type and db_type Forward the former to the latter instead of repeating the same code for both. --- include/soci/oracle/soci-oracle.h | 88 +---------------------- include/soci/soci-backend.h | 108 ++++++++++++---------------- include/soci/sqlite3/soci-sqlite3.h | 23 +----- 3 files changed, 47 insertions(+), 172 deletions(-) diff --git a/include/soci/oracle/soci-oracle.h b/include/soci/oracle/soci-oracle.h index 6224caf5c..7aa870868 100644 --- a/include/soci/oracle/soci-oracle.h +++ b/include/soci/oracle/soci-oracle.h @@ -330,78 +330,6 @@ struct oracle_session_backend : details::session_backend " where table_name = :t"; } - std::string create_column_type(data_type dt, - int precision, int scale) override - { - // Oracle-specific SQL syntax: - - std::string res; - switch (dt) - { - case dt_string: - { - std::ostringstream oss; - - if (precision == 0) - { - oss << "clob"; - } - else - { - oss << "varchar(" << precision << ")"; - } - - res += oss.str(); - } - break; - - case dt_date: - res += "timestamp"; - break; - - case dt_double: - { - std::ostringstream oss; - if (precision == 0) - { - oss << "number"; - } - else - { - oss << "number(" << precision << ", " << scale << ")"; - } - - res += oss.str(); - } - break; - - case dt_integer: - res += "integer"; - break; - - case dt_long_long: - res += "number"; - break; - - case dt_unsigned_long_long: - res += "number"; - break; - - case dt_blob: - res += "blob"; - break; - - case dt_xml: - res += "xmltype"; - break; - - default: - throw soci_error("this data_type is not supported in create_column"); - } - - return res; - } - std::string create_column_type(db_type dt, int precision, int scale) override { @@ -472,18 +400,11 @@ struct oracle_session_backend : details::session_backend break; default: - throw soci_error("this data_type is not supported in create_column"); + 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, data_type dt, - int precision, int scale) override - { - return "alter table " + tableName + " add " + - columnName + " " + create_column_type(dt, precision, scale); - } std::string add_column(const std::string & tableName, const std::string & columnName, db_type dt, int precision, int scale) override @@ -491,13 +412,6 @@ struct oracle_session_backend : details::session_backend return "alter table " + tableName + " add " + columnName + " " + create_column_type(dt, precision, scale); } - std::string alter_column(const std::string & tableName, - const std::string & columnName, data_type dt, - int precision, int scale) override - { - return "alter table " + tableName + " modify " + - 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 diff --git a/include/soci/soci-backend.h b/include/soci/soci-backend.h index 0d9c18fd4..723871674 100644 --- a/include/soci/soci-backend.h +++ b/include/soci/soci-backend.h @@ -89,6 +89,25 @@ enum statement_type 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 @@ -342,53 +361,7 @@ class session_backend { return "truncate table " + tableName; } - // DEPRECATED. USE create_column_type(db_type, int, int) INSTEAD. - virtual std::string create_column_type(data_type dt, - int precision, int scale) - { - // PostgreSQL was selected as a baseline for the syntax: - - std::string res; - switch (dt) - { - case dt_string: - res += create_column_type(db_string, precision, scale); - break; - - case dt_date: - res += create_column_type(db_date, precision, scale); - break; - - case dt_double: - res += create_column_type(db_double, precision, scale); - break; - case dt_integer: - res += create_column_type(db_int32, precision, scale); - break; - - case dt_long_long: - res += create_column_type(db_int64, precision, scale); - break; - - case dt_unsigned_long_long: - res += create_column_type(db_uint64, precision, scale); - break; - - case dt_blob: - res += create_column_type(db_blob, precision, scale); - break; - - case dt_xml: - res += create_column_type(db_xml, precision, scale); - break; - - default: - throw soci_error("this data_type is not supported in create_column"); - } - - return res; - } virtual std::string create_column_type(db_type dt, int precision, int scale) { @@ -463,14 +436,7 @@ class session_backend return res; } - // DEPRECATED. USE add_column(std::string, std::string, db_type, int, int) INSTEAD. - virtual std::string add_column(const std::string & tableName, - const std::string & columnName, data_type dt, - int precision, int scale) - { - return "alter table " + tableName + " add column " + columnName + - " " + create_column_type(dt, precision, scale); - } + virtual std::string add_column(const std::string & tableName, const std::string & columnName, db_type dt, @@ -479,15 +445,6 @@ class session_backend return "alter table " + tableName + " add column " + columnName + " " + create_column_type(dt, precision, scale); } - // DEPRECATED. USE alter_column(std::string, std::string, db_type, int, int) INSTEAD. - virtual std::string alter_column(const std::string & tableName, - const std::string & columnName, data_type dt, - int precision, int scale) - { - return "alter table " + tableName + " alter column " + - columnName + " type " + - create_column_type(dt, precision, scale); - } virtual std::string alter_column(const std::string & tableName, const std::string & columnName, db_type dt, @@ -547,6 +504,31 @@ class session_backend 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_; diff --git a/include/soci/sqlite3/soci-sqlite3.h b/include/soci/sqlite3/soci-sqlite3.h index 28ae3b634..7be99b550 100644 --- a/include/soci/sqlite3/soci-sqlite3.h +++ b/include/soci/sqlite3/soci-sqlite3.h @@ -319,27 +319,6 @@ struct sqlite3_session_backend : details::session_backend return "select name as \"TABLE_NAME\"" " from sqlite_master where type = 'table'"; } - std::string create_column_type(data_type dt, - int , int ) override - { - switch (dt) - { - case dt_xml: - case dt_string: - return "text"; - case dt_double: - return "real"; - case dt_date: - case dt_integer: - case dt_long_long: - case dt_unsigned_long_long: - return "integer"; - case dt_blob: - return "blob"; - default: - throw soci_error("this data_type is not supported in create_column"); - } - } std::string create_column_type(db_type dt, int , int ) override { @@ -363,7 +342,7 @@ struct sqlite3_session_backend : details::session_backend case db_blob: return "blob"; default: - throw soci_error("this data_type is not supported in create_column"); + throw soci_error("this db_type is not supported in create_column"); } } From 75c8fd87c1ffe8731eff4e681993fce71bcd0893 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 3 Jan 2024 00:18:11 +0100 Subject: [PATCH 42/46] Update ddl_type to use db_type too Preserve the functions taking data_type for compatibility. --- include/soci/once-temp-type.h | 30 +++++++++++++++++++++++++----- include/soci/session.h | 24 ++++++++++++++++++++++-- src/core/once-temp-type.cpp | 22 ++-------------------- src/core/session.cpp | 4 ++-- 4 files changed, 51 insertions(+), 29 deletions(-) diff --git a/include/soci/once-temp-type.h b/include/soci/once-temp-type.h index b860d35e8..b1165b46a 100644 --- a/include/soci/once-temp-type.h +++ b/include/soci/once-temp-type.h @@ -126,16 +126,13 @@ class SOCI_DECL ddl_type void create_table(const std::string & tableName); void add_column(const std::string & tableName, - const std::string & columnName, data_type dt, + const std::string & columnName, db_type dt, int precision, int scale); void alter_column(const std::string & tableName, - const std::string & columnName, data_type dt, + const std::string & columnName, db_type dt, int precision, int scale); void drop_column(const std::string & tableName, const std::string & columnName); - // DEPRECATED. USE column(std::string, db_type, int, int) INSTEAD. - ddl_type & column(const std::string & columnName, data_type dt, - int precision = 0, int scale = 0); ddl_type & column(const std::string & columnName, db_type dt, int precision = 0, int scale = 0); ddl_type & unique(const std::string & name, @@ -153,6 +150,29 @@ class SOCI_DECL ddl_type // 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_; diff --git a/include/soci/session.h b/include/soci/session.h index 88207b420..27b5d4b0f 100644 --- a/include/soci/session.h +++ b/include/soci/session.h @@ -152,10 +152,10 @@ class SOCI_DECL session 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, data_type dt, + 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, data_type dt, + 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); @@ -184,6 +184,26 @@ class SOCI_DECL session 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(); diff --git a/src/core/once-temp-type.cpp b/src/core/once-temp-type.cpp index 5e3597c62..740767d57 100644 --- a/src/core/once-temp-type.cpp +++ b/src/core/once-temp-type.cpp @@ -86,7 +86,7 @@ void ddl_type::create_table(const std::string & tableName) } void ddl_type::add_column(const std::string & tableName, - const std::string & columnName, data_type dt, + const std::string & columnName, db_type dt, int precision, int scale) { rcst_->accumulate(s_->get_backend()->add_column( @@ -94,7 +94,7 @@ void ddl_type::add_column(const std::string & tableName, } void ddl_type::alter_column(const std::string & tableName, - const std::string & columnName, data_type dt, + const std::string & columnName, db_type dt, int precision, int scale) { rcst_->accumulate(s_->get_backend()->alter_column( @@ -108,24 +108,6 @@ void ddl_type::drop_column(const std::string & tableName, tableName, columnName)); } -ddl_type & ddl_type::column(const std::string & columnName, data_type dt, - int precision, int scale) -{ - if (rcst_->get_need_comma()) - { - rcst_->accumulate(", "); - } - - rcst_->accumulate(columnName); - rcst_->accumulate(" "); - rcst_->accumulate( - s_->get_backend()->create_column_type(dt, precision, scale)); - - rcst_->set_need_comma(true); - - return *this; -} - ddl_type & ddl_type::column(const std::string & columnName, db_type dt, int precision, int scale) { diff --git a/src/core/session.cpp b/src/core/session.cpp index fc4550ec5..c661e3273 100644 --- a/src/core/session.cpp +++ b/src/core/session.cpp @@ -496,7 +496,7 @@ void session::truncate_table(const std::string & tableName) } ddl_type session::add_column(const std::string & tableName, - const std::string & columnName, data_type dt, + const std::string & columnName, db_type dt, int precision, int scale) { ddl_type ddl(*this); @@ -507,7 +507,7 @@ ddl_type session::add_column(const std::string & tableName, } ddl_type session::alter_column(const std::string & tableName, - const std::string & columnName, data_type dt, + const std::string & columnName, db_type dt, int precision, int scale) { ddl_type ddl(*this); From fdfcc12e8d8feeb65bf343fd676be9327a8cda6a Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 3 Jan 2024 00:36:54 +0100 Subject: [PATCH 43/46] Remove data_type argument from describe_column() backend function This is unnecessary as it can be recovered from db_type: even if this is not lossless, we don't really care about it if all we need is data_type, so simplify the API and the implementation by only having one "type" parameter instead of two. No real changes. --- docs/api/backend.md | 2 +- include/soci/db2/soci-db2.h | 2 +- include/soci/empty/soci-empty.h | 2 +- include/soci/firebird/soci-firebird.h | 2 +- include/soci/mysql/soci-mysql.h | 2 +- include/soci/odbc/soci-odbc.h | 2 +- include/soci/oracle/soci-oracle.h | 2 +- include/soci/postgresql/soci-postgresql.h | 2 +- include/soci/soci-backend.h | 27 +++++- include/soci/sqlite3/soci-sqlite3.h | 2 +- src/backends/db2/statement.cpp | 9 +- src/backends/empty/statement.cpp | 2 +- src/backends/firebird/statement.cpp | 13 --- src/backends/odbc/statement.cpp | 9 +- src/backends/oracle/statement.cpp | 10 +-- src/backends/postgresql/statement.cpp | 10 +-- src/backends/sqlite3/statement.cpp | 101 +++++++++++----------- src/core/statement.cpp | 7 +- 18 files changed, 93 insertions(+), 113 deletions(-) diff --git a/docs/api/backend.md b/docs/api/backend.md index 372ceca9b..691b0fc25 100644 --- a/docs/api/backend.md +++ b/docs/api/backend.md @@ -220,7 +220,7 @@ public: virtual std::string rewrite_for_procedure_call(std::string const& query) = 0; virtual int prepare_for_describe() = 0; - virtual void describe_column(int colNum, data_type& dtype, + virtual void describe_column(int colNum, db_type& dbtype, std::string& column_name) = 0; diff --git a/include/soci/db2/soci-db2.h b/include/soci/db2/soci-db2.h index 5ede930b0..bb33128be 100644 --- a/include/soci/db2/soci-db2.h +++ b/include/soci/db2/soci-db2.h @@ -197,7 +197,7 @@ struct SOCI_DB2_DECL db2_statement_backend : details::statement_backend std::string rewrite_for_procedure_call(std::string const& query) override; int prepare_for_describe() override; - void describe_column(int colNum, data_type& dtype, db_type& dbtype, std::string& columnName) 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; diff --git a/include/soci/empty/soci-empty.h b/include/soci/empty/soci-empty.h index c7c62ec3f..ff2047c41 100644 --- a/include/soci/empty/soci-empty.h +++ b/include/soci/empty/soci-empty.h @@ -114,7 +114,7 @@ struct SOCI_EMPTY_DECL empty_statement_backend : details::statement_backend std::string rewrite_for_procedure_call(std::string const& query) override; int prepare_for_describe() override; - void describe_column(int colNum, data_type& dtype, db_type& dbtype, std::string& columnName) 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; diff --git a/include/soci/firebird/soci-firebird.h b/include/soci/firebird/soci-firebird.h index fef98de02..fbc039679 100644 --- a/include/soci/firebird/soci-firebird.h +++ b/include/soci/firebird/soci-firebird.h @@ -201,7 +201,7 @@ struct firebird_statement_backend : details::statement_backend std::string rewrite_for_procedure_call(std::string const &query) override; int prepare_for_describe() override; - void describe_column(int colNum, data_type &dtype, + void describe_column(int colNum, db_type &dbtype, std::string &columnName) override; diff --git a/include/soci/mysql/soci-mysql.h b/include/soci/mysql/soci-mysql.h index daa2f44bc..7bb61dbc8 100644 --- a/include/soci/mysql/soci-mysql.h +++ b/include/soci/mysql/soci-mysql.h @@ -181,7 +181,7 @@ struct mysql_statement_backend : details::statement_backend std::string rewrite_for_procedure_call(std::string const &query) override; int prepare_for_describe() override; - void describe_column(int colNum, data_type &dtype, + void describe_column(int colNum, db_type &dbtype, std::string &columnName) override; diff --git a/include/soci/odbc/soci-odbc.h b/include/soci/odbc/soci-odbc.h index 833d33711..f449f370b 100644 --- a/include/soci/odbc/soci-odbc.h +++ b/include/soci/odbc/soci-odbc.h @@ -253,7 +253,7 @@ struct odbc_statement_backend : details::statement_backend std::string rewrite_for_procedure_call(std::string const &query) override; int prepare_for_describe() override; - void describe_column(int colNum, data_type &dtype, + void describe_column(int colNum, db_type &dbtype, std::string &columnName) override; diff --git a/include/soci/oracle/soci-oracle.h b/include/soci/oracle/soci-oracle.h index 7aa870868..6406b591c 100644 --- a/include/soci/oracle/soci-oracle.h +++ b/include/soci/oracle/soci-oracle.h @@ -229,7 +229,7 @@ struct oracle_statement_backend : details::statement_backend std::string rewrite_for_procedure_call(std::string const &query) override; int prepare_for_describe() override; - void describe_column(int colNum, data_type &dtype, + void describe_column(int colNum, db_type &dbtype, std::string &columnName) override; diff --git a/include/soci/postgresql/soci-postgresql.h b/include/soci/postgresql/soci-postgresql.h index 594d41034..3e86ac299 100644 --- a/include/soci/postgresql/soci-postgresql.h +++ b/include/soci/postgresql/soci-postgresql.h @@ -270,7 +270,7 @@ struct postgresql_statement_backend : details::statement_backend std::string rewrite_for_procedure_call(std::string const & query) override; int prepare_for_describe() override; - void describe_column(int colNum, data_type & dtype, + void describe_column(int colNum, db_type & dbtype, std::string & columnName) override; diff --git a/include/soci/soci-backend.h b/include/soci/soci-backend.h index 723871674..275a6e8b9 100644 --- a/include/soci/soci-backend.h +++ b/include/soci/soci-backend.h @@ -108,6 +108,31 @@ inline db_type to_db_type(data_type dt) return db_string; } +// this conversion loses information and is only used inside SOCI for +// compatibility with the previous versions that only had data_type +inline data_type to_data_type(db_type dbt) +{ + 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: + case db_uint32: return dt_integer; + 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; +} + // polymorphic into type backend class standard_into_type_backend @@ -244,7 +269,7 @@ class statement_backend virtual std::string rewrite_for_procedure_call(std::string const& query) = 0; virtual int prepare_for_describe() = 0; - virtual void describe_column(int colNum, data_type& dtype, + virtual void describe_column(int colNum, db_type& dbtype, std::string& column_name) = 0; diff --git a/include/soci/sqlite3/soci-sqlite3.h b/include/soci/sqlite3/soci-sqlite3.h index 7be99b550..7c9449ac3 100644 --- a/include/soci/sqlite3/soci-sqlite3.h +++ b/include/soci/sqlite3/soci-sqlite3.h @@ -224,7 +224,7 @@ struct sqlite3_statement_backend : details::statement_backend std::string rewrite_for_procedure_call(std::string const &query) override; int prepare_for_describe() override; - void describe_column(int colNum, data_type &dtype, + void describe_column(int colNum, db_type &dbtype, std::string &columnName) override; diff --git a/src/backends/db2/statement.cpp b/src/backends/db2/statement.cpp index 1c154fb46..751959a21 100644 --- a/src/backends/db2/statement.cpp +++ b/src/backends/db2/statement.cpp @@ -225,7 +225,7 @@ int db2_statement_backend::prepare_for_describe() } void db2_statement_backend::describe_column(int colNum, - data_type & type, db_type & dbtype, std::string & columnName ) + db_type & dbtype, std::string & columnName ) { SQLCHAR colNameBuffer[2048]; SQLSMALLINT colNameBufferOverflow; @@ -252,7 +252,6 @@ SQLCHAR colNameBuffer[2048]; case SQL_TYPE_DATE: case SQL_TYPE_TIME: case SQL_TYPE_TIMESTAMP: - type = dt_date; dbtype = db_date; break; case SQL_DOUBLE: @@ -260,30 +259,24 @@ SQLCHAR colNameBuffer[2048]; case SQL_REAL: case SQL_FLOAT: case SQL_NUMERIC: - type = dt_double; dbtype = db_double; break; case SQL_TINYINT: - type = dt_integer; dbtype = db_int8; break; case SQL_SMALLINT: - type = dt_integer; dbtype = db_int16; break; case SQL_INTEGER: - type = dt_integer; dbtype = db_int32; break; case SQL_BIGINT: - type = dt_long_long; dbtype = db_int64; break; case SQL_CHAR: case SQL_VARCHAR: case SQL_LONGVARCHAR: default: - type = dt_string; dbtype = db_string; break; } diff --git a/src/backends/empty/statement.cpp b/src/backends/empty/statement.cpp index 045bee5cd..2dea33129 100644 --- a/src/backends/empty/statement.cpp +++ b/src/backends/empty/statement.cpp @@ -82,7 +82,7 @@ int empty_statement_backend::prepare_for_describe() } void empty_statement_backend::describe_column(int /* colNum */, - data_type & /* type */, db_type & /* dbtype */, + db_type & /* dbtype */, std::string & /* columnName */) { // ... diff --git a/src/backends/firebird/statement.cpp b/src/backends/firebird/statement.cpp index 0249543c5..aa58ca46c 100644 --- a/src/backends/firebird/statement.cpp +++ b/src/backends/firebird/statement.cpp @@ -658,7 +658,6 @@ int firebird_statement_backend::prepare_for_describe() } void firebird_statement_backend::describe_column(int colNum, - data_type & type, db_type & dbtype, std::string & columnName) { @@ -670,18 +669,15 @@ void firebird_statement_backend::describe_column(int colNum, { case SQL_TEXT: case SQL_VARYING: - type = dt_string; dbtype = db_string; break; case SQL_TYPE_DATE: case SQL_TYPE_TIME: case SQL_TIMESTAMP: - type = dt_date; dbtype = db_date; break; case SQL_FLOAT: case SQL_DOUBLE: - type = dt_double; dbtype = db_double; break; case SQL_SHORT: @@ -689,18 +685,15 @@ void firebird_statement_backend::describe_column(int colNum, { if (session_.get_option_decimals_as_strings()) { - type = dt_string; dbtype = db_string; } else { - type = dt_double; dbtype = db_double; } } else { - type = dt_integer; dbtype = db_int16; } break; @@ -709,18 +702,15 @@ void firebird_statement_backend::describe_column(int colNum, { if (session_.get_option_decimals_as_strings()) { - type = dt_string; dbtype = db_string; } else { - type = dt_double; dbtype = db_double; } } else { - type = dt_integer; dbtype = db_int32; } break; @@ -729,18 +719,15 @@ void firebird_statement_backend::describe_column(int colNum, { if (session_.get_option_decimals_as_strings()) { - type = dt_string; dbtype = db_string; } else { - type = dt_double; dbtype = db_double; } } else { - type = dt_long_long; dbtype = db_int64; } break; diff --git a/src/backends/odbc/statement.cpp b/src/backends/odbc/statement.cpp index 816953f1a..2addd31c2 100644 --- a/src/backends/odbc/statement.cpp +++ b/src/backends/odbc/statement.cpp @@ -327,7 +327,7 @@ int odbc_statement_backend::prepare_for_describe() return numCols; } -void odbc_statement_backend::describe_column(int colNum, data_type & type, +void odbc_statement_backend::describe_column(int colNum, db_type & dbtype, std::string & columnName) { @@ -369,7 +369,6 @@ void odbc_statement_backend::describe_column(int colNum, data_type & type, case SQL_TYPE_DATE: case SQL_TYPE_TIME: case SQL_TYPE_TIMESTAMP: - type = dt_date; dbtype = db_date; break; case SQL_DOUBLE: @@ -377,30 +376,24 @@ void odbc_statement_backend::describe_column(int colNum, data_type & type, case SQL_REAL: case SQL_FLOAT: case SQL_NUMERIC: - type = dt_double; dbtype = db_double; break; case SQL_TINYINT: - type = dt_integer; dbtype = is_unsigned == SQL_TRUE ? db_uint8 : db_int8; break; case SQL_SMALLINT: - type = dt_integer; dbtype = is_unsigned == SQL_TRUE ? db_uint16 : db_int16; break; case SQL_INTEGER: - type = dt_integer; dbtype = is_unsigned == SQL_TRUE ? db_uint32 : db_int32; break; case SQL_BIGINT: - type = dt_long_long; dbtype = is_unsigned == SQL_TRUE ? db_uint64 : db_int64; break; case SQL_CHAR: case SQL_VARCHAR: case SQL_LONGVARCHAR: default: - type = dt_string; dbtype = db_string; break; } diff --git a/src/backends/oracle/statement.cpp b/src/backends/oracle/statement.cpp index 4a506bc71..0db66132a 100644 --- a/src/backends/oracle/statement.cpp +++ b/src/backends/oracle/statement.cpp @@ -184,7 +184,7 @@ int oracle_statement_backend::prepare_for_describe() return cols; } -void oracle_statement_backend::describe_column(int colNum, data_type &type, +void oracle_statement_backend::describe_column(int colNum, db_type &xdbtype, std::string &columnName) { @@ -286,7 +286,6 @@ void oracle_statement_backend::describe_column(int colNum, data_type &type, { case SQLT_CHR: case SQLT_AFC: - type = dt_string; xdbtype = db_string; break; case SQLT_NUM: @@ -294,37 +293,30 @@ void oracle_statement_backend::describe_column(int colNum, data_type &type, { if (session_.get_option_decimals_as_strings()) { - type = dt_string; xdbtype = db_string; } else { - type = dt_double; xdbtype = db_double; } } else if (dbprec <= std::numeric_limits::digits10) { - type = dt_integer; xdbtype = db_int32; } else { - type = dt_long_long; xdbtype = db_int64; } break; case OCI_TYPECODE_BDOUBLE: - type = dt_double; xdbtype = db_double; break; case SQLT_DAT: - type = dt_date; xdbtype = db_date; break; default: // Unknown oracle types will just be represented by a string - type = dt_string; xdbtype = db_string; } } diff --git a/src/backends/postgresql/statement.cpp b/src/backends/postgresql/statement.cpp index 388661094..f67c7bbba 100644 --- a/src/backends/postgresql/statement.cpp +++ b/src/backends/postgresql/statement.cpp @@ -740,7 +740,7 @@ void throw_soci_type_error(Oid typeOid, int colNum, char category, const char* t throw soci_error(message.str()); } -void postgresql_statement_backend::describe_column(int colNum, data_type & type, +void postgresql_statement_backend::describe_column(int colNum, db_type & dbtype, std::string & columnName) { // In postgresql_ column numbers start from 0 @@ -764,7 +764,6 @@ void postgresql_statement_backend::describe_column(int colNum, data_type & type, case 114: // json case 17: // bytea case 2950: // uuid - type = dt_string; dbtype = db_string; break; @@ -775,35 +774,29 @@ void postgresql_statement_backend::describe_column(int colNum, data_type & type, case 1114: // timestamp case 1184: // timestamptz case 1266: // timetz - type = dt_date; dbtype = db_date; break; case 700: // float4 case 701: // float8 case 1700: // numeric - type = dt_double; dbtype = db_double; break; case 16: // bool - type = dt_integer; dbtype = db_int8; break; case 21: // int2 - type = dt_integer; dbtype = db_int16; break; case 23: // int4 case 26: // oid - type = dt_integer; dbtype = db_int32; break; case 20: // int8 - type = dt_long_long; dbtype = db_int64; break; @@ -839,7 +832,6 @@ void postgresql_statement_backend::describe_column(int colNum, data_type & type, case 'T': // time type case 'S': // string type case 'U': // user type - type = dt_string; dbtype = db_string; break; diff --git a/src/backends/sqlite3/statement.cpp b/src/backends/sqlite3/statement.cpp index 8b1db7145..c852df4b0 100644 --- a/src/backends/sqlite3/statement.cpp +++ b/src/backends/sqlite3/statement.cpp @@ -116,11 +116,10 @@ sqlite3_statement_backend::load_rowset(int totalRows) if (columns_.empty()) { numCols = sqlite3_column_count(stmt_); - data_type type; db_type dbtype; std::string name; for (int c = 1; c <= numCols; ++c) - describe_column(c, type, dbtype, name); + describe_column(c, dbtype, name); } else numCols = static_cast(columns_.size()); @@ -443,57 +442,62 @@ int sqlite3_statement_backend::prepare_for_describe() return sqlite3_column_count(stmt_); } -typedef std::map> sqlite3_data_type_map; +typedef std::map sqlite3_data_type_map; static sqlite3_data_type_map get_data_type_map() { sqlite3_data_type_map m; // Spaces are removed from decltype before looking up in this map, so we don't use them here as well - m["blob"] = { dt_blob, db_blob }; - - m["date"] = { dt_date, db_date }; - m["time"] = { dt_date, db_date }; - m["datetime"] = { dt_date, db_date }; - m["timestamp"] = { dt_date, db_date }; - - m["decimal"] = { dt_double, db_double }; - m["double"] = { dt_double, db_double }; - m["doubleprecision"] = { dt_double, db_double }; - m["float"] = { dt_double, db_double }; - m["number"] = { dt_double, db_double }; - m["numeric"] = { dt_double, db_double }; - m["real"] = { dt_double, db_double }; - - m["tinyint"] = { dt_integer, db_int8 }; - - m["smallint"] = { dt_integer, db_int16 }; - - m["boolean"] = { dt_integer, db_int32 }; - m["int"] = { dt_integer, db_int32 }; - m["integer"] = { dt_integer, db_int32 }; - m["int2"] = { dt_integer, db_int32 }; - m["mediumint"] = { dt_integer, db_int32 }; - - m["bigint"] = { dt_long_long, db_int64 }; - m["int8"] = { dt_long_long, db_int64 }; - - m["char"] = { dt_string, db_string }; - m["character"] = { dt_string, db_string }; - m["clob"] = { dt_string, db_string }; - m["nativecharacter"] = { dt_string, db_string }; - m["nchar"] = { dt_string, db_string }; - m["nvarchar"] = { dt_string, db_string }; - m["text"] = { dt_string, db_string }; - m["varchar"] = { dt_string, db_string }; - m["varyingcharacter"] = { dt_string, db_string }; - - m["unsignedbigint"] = { dt_unsigned_long_long, db_uint64 }; + // db_blob + m["blob"] = db_blob; + + // db_date + m["date"] = db_date; + m["time"] = db_date; + m["datetime"] = db_date; + m["timestamp"] = db_date; + + // db_double + m["decimal"] = db_double; + m["double"] = db_double; + m["doubleprecision"] = db_double; + m["float"] = db_double; + m["number"] = db_double; + m["numeric"] = db_double; + m["real"] = db_double; + + // integer types + m["tinyint"] = db_int8; + + m["smallint"] = db_int16; + + m["boolean"] = db_int32; + m["int"] = db_int32; + m["integer"] = db_int32; + m["int2"] = db_int32; + m["mediumint"] = db_int32; + + m["bigint"] = db_int64; + m["int8"] = db_int64; + + m["unsignedbigint"] = db_uint64; + + // db_string + m["char"] = db_string; + m["character"] = db_string; + m["clob"] = db_string; + m["nativecharacter"] = db_string; + m["nchar"] = db_string; + m["nvarchar"] = db_string; + m["text"] = db_string; + m["varchar"] = db_string; + m["varyingcharacter"] = db_string; return m; } -void sqlite3_statement_backend::describe_column(int colNum, data_type & type, +void sqlite3_statement_backend::describe_column(int colNum, db_type & dbtype, std::string & columnName) { @@ -506,7 +510,6 @@ void sqlite3_statement_backend::describe_column(int colNum, data_type & type, if (!coldef.name_.empty()) { columnName = coldef.name_; - type = coldef.type_; dbtype = coldef.dataType_; return; } @@ -541,8 +544,8 @@ void sqlite3_statement_backend::describe_column(int colNum, data_type & type, sqlite3_data_type_map::const_iterator iter = dataTypeMap.find(dt); if (iter != dataTypeMap.end()) { - coldef.type_ = type = iter->second.first; - coldef.dataType_ = dbtype = iter->second.second; + coldef.dataType_ = dbtype = iter->second; + coldef.type_ = details::to_data_type(dbtype); return; } @@ -556,25 +559,21 @@ void sqlite3_statement_backend::describe_column(int colNum, data_type & type, switch (sqlite3_type) { case SQLITE_INTEGER: - type = dt_integer; dbtype = db_int32; break; case SQLITE_FLOAT: - type = dt_double; dbtype = db_double; break; case SQLITE_BLOB: case SQLITE_TEXT: - type = dt_string; dbtype = db_string; break; default: - type = dt_string; dbtype = db_string; break; } - coldef.type_ = type; coldef.dataType_ = dbtype; + coldef.type_ = details::to_data_type(dbtype); sqlite3_reset(stmt_); } diff --git a/src/core/statement.cpp b/src/core/statement.cpp index f5a7000f6..bb6530adf 100644 --- a/src/core/statement.cpp +++ b/src/core/statement.cpp @@ -702,16 +702,15 @@ void statement_impl::describe() int const numcols = backEnd_->prepare_for_describe(); for (int i = 1; i <= numcols; ++i) { - data_type dtype; db_type dbtype; std::string columnName; - backEnd_->describe_column(i, dtype, dbtype, columnName); + backEnd_->describe_column(i, dbtype, columnName); column_properties props; props.set_name(columnName); - props.set_data_type(dtype); props.set_db_type(dbtype); + props.set_data_type(details::to_data_type(dbtype)); switch (dbtype) { @@ -752,7 +751,7 @@ void statement_impl::describe() break; default: std::ostringstream msg; - msg << "db column type " << dtype + msg << "db column type " << dbtype <<" not supported for dynamic selects"< Date: Wed, 3 Jan 2024 00:59:05 +0100 Subject: [PATCH 44/46] Remove data_type argument from MySQL backend describe_column() too This should have been part of fdfcc12e (Remove data_type argument from describe_column() backend function, 2024-01-03) but was forgotten there. --- src/backends/mysql/statement.cpp | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/backends/mysql/statement.cpp b/src/backends/mysql/statement.cpp index cd901602d..33cdfc61f 100644 --- a/src/backends/mysql/statement.cpp +++ b/src/backends/mysql/statement.cpp @@ -402,45 +402,38 @@ int mysql_statement_backend::prepare_for_describe() } void mysql_statement_backend::describe_column(int colNum, - data_type & type, db_type & dbtype, std::string & columnName) + db_type & dbtype, std::string & columnName) { int pos = colNum - 1; MYSQL_FIELD *field = mysql_fetch_field_direct(result_, pos); switch (field->type) { case FIELD_TYPE_CHAR: //MYSQL_TYPE_TINY: - type = dt_integer; dbtype = field->flags & UNSIGNED_FLAG ? db_uint8 : db_int8; break; case FIELD_TYPE_SHORT: //MYSQL_TYPE_SHORT: - type = dt_integer; dbtype = field->flags & UNSIGNED_FLAG ? db_uint16 : db_int16; break; case FIELD_TYPE_INT24: //MYSQL_TYPE_INT24: - type = dt_integer; dbtype = field->flags & UNSIGNED_FLAG ? db_uint32 : db_int32; break; case FIELD_TYPE_LONG: //MYSQL_TYPE_LONG: if (field->flags & UNSIGNED_FLAG) { - type = dt_long_long; dbtype = db_uint32; } else { - type = dt_integer; dbtype = db_int32; } break; case FIELD_TYPE_LONGLONG: //MYSQL_TYPE_LONGLONG: if (field->flags & UNSIGNED_FLAG) { - type = dt_unsigned_long_long; dbtype = db_uint64; } else { - type = dt_long_long; dbtype = db_int64; } break; @@ -452,7 +445,6 @@ void mysql_statement_backend::describe_column(int colNum, // sends field type number 246, no matter which version of libraries // the client is using. case 246: //MYSQL_TYPE_NEWDECIMAL: - type = dt_double; dbtype = db_double; break; case FIELD_TYPE_TIMESTAMP: //MYSQL_TYPE_TIMESTAMP: @@ -461,7 +453,6 @@ void mysql_statement_backend::describe_column(int colNum, case FIELD_TYPE_DATETIME: //MYSQL_TYPE_DATETIME: case FIELD_TYPE_YEAR: //MYSQL_TYPE_YEAR: case FIELD_TYPE_NEWDATE: //MYSQL_TYPE_NEWDATE: - type = dt_date; dbtype = db_date; break; // case MYSQL_TYPE_VARCHAR: @@ -472,7 +463,6 @@ void mysql_statement_backend::describe_column(int colNum, case FIELD_TYPE_TINY_BLOB: case FIELD_TYPE_MEDIUM_BLOB: case FIELD_TYPE_LONG_BLOB: - type = dt_string; dbtype = db_string; break; default: From a9b350888011594237053d8ce2be694d641eccbe Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 3 Jan 2024 01:29:55 +0100 Subject: [PATCH 45/46] Make db_type to data_type conversion backend-dependent It wasn't quite the same for all of them, notably MySQL and ODBC disagreed about the mapping of db_uint32 and ODBC backend also mapped db_uint64 to signed dt_long_long and not dt_unsigned_long_long as the other backends, so make it possible to preserve its existing behaviour by overriding to_data_type() in it. There is still a minor incompatibility in MySQL backend: the type of unsigned INT24 fields is now dt_long_long and not dt_integer as before, but we can hopefully live with this. --- include/soci/odbc/soci-odbc.h | 1 + include/soci/soci-backend.h | 51 +++++++++++++++--------------- src/backends/odbc/statement.cpp | 12 +++++++ src/backends/sqlite3/statement.cpp | 4 +-- src/core/statement.cpp | 2 +- 5 files changed, 42 insertions(+), 28 deletions(-) diff --git a/include/soci/odbc/soci-odbc.h b/include/soci/odbc/soci-odbc.h index f449f370b..2455306f9 100644 --- a/include/soci/odbc/soci-odbc.h +++ b/include/soci/odbc/soci-odbc.h @@ -256,6 +256,7 @@ struct odbc_statement_backend : details::statement_backend 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 std::size_t column_size(int position); diff --git a/include/soci/soci-backend.h b/include/soci/soci-backend.h index 275a6e8b9..ffb9099aa 100644 --- a/include/soci/soci-backend.h +++ b/include/soci/soci-backend.h @@ -108,31 +108,6 @@ inline db_type to_db_type(data_type dt) return db_string; } -// this conversion loses information and is only used inside SOCI for -// compatibility with the previous versions that only had data_type -inline data_type to_data_type(db_type dbt) -{ - 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: - case db_uint32: return dt_integer; - 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; -} - // polymorphic into type backend class standard_into_type_backend @@ -273,6 +248,32 @@ class statement_backend 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; diff --git a/src/backends/odbc/statement.cpp b/src/backends/odbc/statement.cpp index 2addd31c2..2f61df2e0 100644 --- a/src/backends/odbc/statement.cpp +++ b/src/backends/odbc/statement.cpp @@ -399,6 +399,18 @@ void odbc_statement_backend::describe_column(int colNum, } } +data_type odbc_statement_backend::to_data_type(db_type dbt) const +{ + // Before adding db_type, this backend returned signed integer constants + // even for unsigned types, so preserve this behaviour. + switch (dbt) + { + case db_uint32: return dt_integer; + case db_uint64: return dt_long_long; + default: return statement_backend::to_data_type(dbt); + } +} + std::size_t odbc_statement_backend::column_size(int colNum) { SQLCHAR colNameBuffer[2048]; diff --git a/src/backends/sqlite3/statement.cpp b/src/backends/sqlite3/statement.cpp index c852df4b0..c21909be0 100644 --- a/src/backends/sqlite3/statement.cpp +++ b/src/backends/sqlite3/statement.cpp @@ -545,7 +545,7 @@ void sqlite3_statement_backend::describe_column(int colNum, if (iter != dataTypeMap.end()) { coldef.dataType_ = dbtype = iter->second; - coldef.type_ = details::to_data_type(dbtype); + coldef.type_ = to_data_type(dbtype); return; } @@ -573,7 +573,7 @@ void sqlite3_statement_backend::describe_column(int colNum, break; } coldef.dataType_ = dbtype; - coldef.type_ = details::to_data_type(dbtype); + coldef.type_ = to_data_type(dbtype); sqlite3_reset(stmt_); } diff --git a/src/core/statement.cpp b/src/core/statement.cpp index bb6530adf..495cca58e 100644 --- a/src/core/statement.cpp +++ b/src/core/statement.cpp @@ -710,7 +710,7 @@ void statement_impl::describe() column_properties props; props.set_name(columnName); props.set_db_type(dbtype); - props.set_data_type(details::to_data_type(dbtype)); + props.set_data_type(backEnd_->to_data_type(dbtype)); switch (dbtype) { From 41dc500d5e11cf4ac7f3d79c639cf22eb811ad90 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 3 Jan 2024 17:18:23 +0100 Subject: [PATCH 46/46] Fix compatibility for MySQL MEDIUMINT UNSIGNED columns type Add a hack to still return dt_integer for them instead of dt_long_long returned for the other columns of db_uint32 type. --- include/soci/mysql/soci-mysql.h | 5 +++++ src/backends/mysql/statement.cpp | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/include/soci/mysql/soci-mysql.h b/include/soci/mysql/soci-mysql.h index 7bb61dbc8..7a45bee8e 100644 --- a/include/soci/mysql/soci-mysql.h +++ b/include/soci/mysql/soci-mysql.h @@ -184,6 +184,7 @@ struct mysql_statement_backend : details::statement_backend 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; @@ -210,6 +211,10 @@ struct mysql_statement_backend : details::statement_backend 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 resultRowOffsets_; diff --git a/src/backends/mysql/statement.cpp b/src/backends/mysql/statement.cpp index 33cdfc61f..f38db1f29 100644 --- a/src/backends/mysql/statement.cpp +++ b/src/backends/mysql/statement.cpp @@ -404,6 +404,8 @@ int mysql_statement_backend::prepare_for_describe() void mysql_statement_backend::describe_column(int colNum, db_type & dbtype, std::string & columnName) { + lastDescribedUnsignedMediumInt_ = false; + int pos = colNum - 1; MYSQL_FIELD *field = mysql_fetch_field_direct(result_, pos); switch (field->type) @@ -416,6 +418,8 @@ void mysql_statement_backend::describe_column(int colNum, break; case FIELD_TYPE_INT24: //MYSQL_TYPE_INT24: dbtype = field->flags & UNSIGNED_FLAG ? db_uint32 : db_int32; + if (dbtype == db_uint32) + lastDescribedUnsignedMediumInt_ = true; break; case FIELD_TYPE_LONG: //MYSQL_TYPE_LONG: if (field->flags & UNSIGNED_FLAG) @@ -472,6 +476,22 @@ void mysql_statement_backend::describe_column(int colNum, columnName = field->name; } +data_type mysql_statement_backend::to_data_type(db_type dbt) const +{ + // Before adding db_type, this backend returned dt_integer for 24 bit + // unsigned values but dt_long_long for 32 bit unsigned ones and now we + // return the same db_uint32 for both and translate it to different legacy + // values depending on the flag set by describe_column(). This is pretty + // ugly but needed to preserve compatibility for the people who use MySQL + // MEDIUMINT UNSIGNED with SOCI. + if (lastDescribedUnsignedMediumInt_ && dbt == db_uint32) + { + return dt_integer; + } + + return statement_backend::to_data_type(dbt); +} + mysql_standard_into_type_backend * mysql_statement_backend::make_into_type_backend() {