Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Complete support for C++ integer types #954

Merged
merged 38 commits into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
7644240
Update core code for complete integer type support
zann1x Apr 5, 2022
53f6aba
Update MySQL backend for complete integer type support
zann1x Apr 5, 2022
f27f144
Update SQLite3 backend for complete integer type support
zann1x Apr 5, 2022
dd45b6d
Update PostgreSQL backend for complete integer type support
zann1x Apr 5, 2022
8fc34db
Update Oracle backend for complete integer type support
zann1x Apr 5, 2022
9d0d7c4
Update DB2 backend for complete integer type support
zann1x Apr 5, 2022
e0d0038
Update Firebird backend for complete integer type support
zann1x Apr 5, 2022
6aa6aa7
Update ODBC backend for complete integer type support
zann1x Apr 5, 2022
ca28449
Update soci-simple for complete integer type support
zann1x Apr 5, 2022
9e39f97
Update shared unit tests for complete integer type support
zann1x Apr 5, 2022
8544cab
Update unit tests of MySQL backend for complete integer type support
zann1x Apr 5, 2022
44a4365
Update unit tests of SQLite3 backend for complete integer type support
zann1x Apr 7, 2022
236966f
Update unit tests of PostgreSQL backend for complete integer type
zann1x Apr 5, 2022
0a8f450
Update unit tests of Oracle backend for complete integer type support
zann1x Apr 5, 2022
455a580
Update unit tests of DB2 backend for complete integer type support
zann1x May 8, 2022
b56224e
Update unit test of Firebird backend for complete integer type support
zann1x Apr 5, 2022
43ab82f
Update unit tests of ODBC backend for complete integer type support
zann1x May 8, 2022
71d9b87
Add *_int and *_long_long methods back to the soci-simple API
zann1x Jun 18, 2022
d4414a3
Update docs for complete integer type support
zann1x Jun 18, 2022
8dba000
Correct ODBC error message for unsigned types
zann1x Oct 5, 2022
3d16170
Replace stdint.h with cstdint
zann1x Sep 28, 2022
ff90687
Add back removed dt_* and x_* types
zann1x Oct 5, 2022
367c0c0
Revert unnecessary changes in unit tests
zann1x Oct 5, 2022
4e80322
Fix header include order
zann1x Nov 29, 2022
d95c716
Remove abbreviation in user-facing ODBC error message
zann1x Nov 29, 2022
a824ac8
Fix incorrect extraction of Postgres bool type
zann1x Nov 29, 2022
ede341c
Remove unnecessary type casts
zann1x Dec 31, 2022
60da2f0
Merge separate integer unit tests into one
zann1x Dec 31, 2022
4c36213
Remove unsigned type support checks in unit tests
zann1x Dec 31, 2022
88e2cb4
Fix uint64 vector unit tests
zann1x Jan 3, 2023
ea4ce9d
Simplify platform-specific data type defines
zann1x Dec 30, 2022
e8e4fc9
Fix MSSQL ODBC unit tests
zann1x Jan 4, 2023
4de379f
Fix Postgres unit test
zann1x Jan 8, 2023
1c3e069
Fix MySQL ODBC unit tests
zann1x Jan 15, 2023
ff7e29c
Handle potential overflow in mysql into-conversion
zann1x Aug 13, 2023
826fa77
Expose new db_type for dynamic type mapping
zann1x Aug 11, 2023
037a332
Add db_type description to docs
zann1x Oct 18, 2023
06b68c2
Forward create_column_type() to db_type overload
zann1x Oct 18, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 33 additions & 8 deletions include/private/soci-exchange-cast.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "soci/type-wrappers.h"

#include <ctime>
#include <stdint.h>

namespace soci
{
Expand All @@ -35,27 +36,51 @@ struct exchange_type_traits<x_stdstring>
};

template <>
struct exchange_type_traits<x_short>
struct exchange_type_traits<x_int8>
{
typedef short value_type;
typedef int8_t value_type;
};

template <>
struct exchange_type_traits<x_integer>
struct exchange_type_traits<x_uint8>
{
typedef int value_type;
typedef uint8_t value_type;
};

template <>
struct exchange_type_traits<x_long_long>
struct exchange_type_traits<x_int16>
{
typedef long long value_type;
typedef int16_t value_type;
};

template <>
struct exchange_type_traits<x_unsigned_long_long>
struct exchange_type_traits<x_uint16>
{
typedef unsigned long long value_type;
typedef uint16_t value_type;
};

template <>
struct exchange_type_traits<x_int32>
{
typedef int32_t value_type;
};

template <>
struct exchange_type_traits<x_uint32>
{
typedef uint32_t value_type;
};

template <>
struct exchange_type_traits<x_int64>
{
typedef int64_t value_type;
};

template <>
struct exchange_type_traits<x_uint64>
{
typedef uint64_t value_type;
};

template <>
Expand Down
64 changes: 44 additions & 20 deletions include/private/soci-vector-helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,22 @@ inline std::size_t get_vector_size(exchange_type e, void *data)
return exchange_vector_type_cast<x_char>(data).size();
case x_stdstring:
return exchange_vector_type_cast<x_stdstring>(data).size();
case x_short:
return exchange_vector_type_cast<x_short>(data).size();
case x_integer:
return exchange_vector_type_cast<x_integer>(data).size();
case x_long_long:
return exchange_vector_type_cast<x_long_long>(data).size();
case x_unsigned_long_long:
return exchange_vector_type_cast<x_unsigned_long_long>(data).size();
case x_int8:
return exchange_vector_type_cast<x_int8>(data).size();
case x_uint8:
return exchange_vector_type_cast<x_uint8>(data).size();
case x_int16:
return exchange_vector_type_cast<x_int16>(data).size();
case x_uint16:
return exchange_vector_type_cast<x_uint16>(data).size();
case x_int32:
return exchange_vector_type_cast<x_int32>(data).size();
case x_uint32:
return exchange_vector_type_cast<x_uint32>(data).size();
case x_int64:
return exchange_vector_type_cast<x_int64>(data).size();
case x_uint64:
return exchange_vector_type_cast<x_uint64>(data).size();
case x_double:
return exchange_vector_type_cast<x_double>(data).size();
case x_stdtm:
Expand Down Expand Up @@ -68,17 +76,29 @@ inline void resize_vector(exchange_type e, void *data, std::size_t newSize)
case x_stdstring:
exchange_vector_type_cast<x_stdstring>(data).resize(newSize);
return;
case x_short:
exchange_vector_type_cast<x_short>(data).resize(newSize);
case x_int8:
exchange_vector_type_cast<x_int8>(data).resize(newSize);
return;
case x_integer:
exchange_vector_type_cast<x_integer>(data).resize(newSize);
case x_uint8:
exchange_vector_type_cast<x_uint8>(data).resize(newSize);
return;
case x_long_long:
exchange_vector_type_cast<x_long_long>(data).resize(newSize);
case x_int16:
exchange_vector_type_cast<x_int16>(data).resize(newSize);
return;
case x_unsigned_long_long:
exchange_vector_type_cast<x_unsigned_long_long>(data).resize(newSize);
case x_uint16:
exchange_vector_type_cast<x_uint16>(data).resize(newSize);
return;
case x_int32:
exchange_vector_type_cast<x_int32>(data).resize(newSize);
return;
case x_uint32:
exchange_vector_type_cast<x_uint32>(data).resize(newSize);
return;
case x_int64:
exchange_vector_type_cast<x_int64>(data).resize(newSize);
return;
case x_uint64:
exchange_vector_type_cast<x_uint64>(data).resize(newSize);
return;
case x_double:
exchange_vector_type_cast<x_double>(data).resize(newSize);
Expand Down Expand Up @@ -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<x_longstring>(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:
Expand Down
33 changes: 25 additions & 8 deletions include/soci/column-info.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include "soci/type-conversion.h"
#include "soci/values.h"

#include <stdint.h>

namespace soci
{

Expand Down Expand Up @@ -39,15 +41,30 @@ struct type_conversion<column_info>
case dt_double:
return static_cast<std::size_t>(
v.get<double>(field_name, 0.0));
case dt_integer:
case dt_int8:
return static_cast<std::size_t>(
v.get<int8_t>(field_name, 0));
case dt_uint8:
return static_cast<std::size_t>(
v.get<uint8_t>(field_name, 0));
case dt_int16:
return static_cast<std::size_t>(
v.get<int16_t>(field_name, 0));
case dt_uint16:
return static_cast<std::size_t>(
v.get<uint16_t>(field_name, 0));
case dt_int32:
return static_cast<std::size_t>(
v.get<int32_t>(field_name, 0));
case dt_uint32:
return static_cast<std::size_t>(
v.get<int>(field_name, 0));
case dt_long_long:
v.get<uint32_t>(field_name, 0));
case dt_int64:
return static_cast<std::size_t>(
v.get<long long>(field_name, 0ll));
case dt_unsigned_long_long:
v.get<int64_t>(field_name, 0ll));
case dt_uint64:
return static_cast<std::size_t>(
v.get<unsigned long long>(field_name, 0ull));
v.get<uint64_t>(field_name, 0ull));
break;
default:
return 0u;
Expand All @@ -72,7 +89,7 @@ struct type_conversion<column_info>
}
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 ||
Expand All @@ -85,7 +102,7 @@ struct type_conversion<column_info>
}
else
{
ci.type = dt_integer;
ci.type = dt_int32;
}
}
else if (type_name.find("time") != std::string::npos ||
Expand Down
76 changes: 56 additions & 20 deletions include/soci/exchange-traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "soci/type-wrappers.h"
// std
#include <ctime>
#include <stdint.h>
#include <string>
#include <vector>

Expand Down Expand Up @@ -43,66 +44,94 @@ struct exchange_traits
};

template <>
struct exchange_traits<short>
struct exchange_traits<int8_t>
{
typedef basic_type_tag type_family;
enum { x_type = x_short };
enum { x_type = x_int8 };
};

template <>
struct exchange_traits<unsigned short> : exchange_traits<short>
struct exchange_traits<uint8_t>
{
typedef basic_type_tag type_family;
enum { x_type = x_uint8 };
};

template <>
struct exchange_traits<int>
struct exchange_traits<int16_t>
{
typedef basic_type_tag type_family;
enum { x_type = x_integer };
enum { x_type = x_int16 };
};

template <>
struct exchange_traits<unsigned int> : exchange_traits<int>
struct exchange_traits<uint16_t>
{
typedef basic_type_tag type_family;
enum { x_type = x_uint16 };
};

template <>
struct exchange_traits<char>
struct exchange_traits<int32_t>
{
typedef basic_type_tag type_family;
enum { x_type = x_char };
enum { x_type = x_int32 };
};

template <>
struct exchange_traits<long long>
struct exchange_traits<uint32_t>
{
typedef basic_type_tag type_family;
enum { x_type = x_long_long };
enum { x_type = x_uint32 };
};

template <>
struct exchange_traits<unsigned long long>
struct exchange_traits<int64_t>
{
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<int long_size> 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<long int>
struct exchange_traits<uint64_t>
{
typedef basic_type_tag type_family;
enum { x_type = long_traits_helper<sizeof(long int)>::x_type };
enum { x_type = x_uint64 };
};

#if defined(_WIN64)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to avoid repeating the specializations themselves and just define something like SOCI_LONG_T as either int32_t or int64_t depending on the platform once in fixed-size-ints.h and then write

template <>
struct exchange_traits<long> : exchange_traits<SOCI_LONG_T>
{
};

(and the same for unsigned, of course).

This would be more maintainable and facilitate any further changes and we will need change this because:

  1. We need to specialize it for 64 bit types under Win64.
  2. Even more importantly, we also still need to handle Win32, building for which would currently result in an error AFAICS (and which makes me realize that we don't test Win32 builds any longer).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite like the idea of defining a "new" type for this. Instead of it, I added more descriptive defines. I think that these can also handle the 32-bit case now.
Let me know what you think about this.

template <>
struct exchange_traits<long> : exchange_traits<int32_t>
{
};

template <>
struct exchange_traits<unsigned long> : exchange_traits<uint32_t>
{
};
#elif defined(__APPLE__)
template <>
struct exchange_traits<long> : exchange_traits<int64_t>
{
};

template <>
struct exchange_traits<unsigned long> : exchange_traits<uint64_t>
{
};
#elif defined(__LP64__) || (__WORDSIZE == 64)
template <>
struct exchange_traits<long long> : exchange_traits<int64_t>
{
};

template <>
struct exchange_traits<unsigned long> : exchange_traits<long>
struct exchange_traits<unsigned long long> : exchange_traits<uint64_t>
{
};
#else
#error "Unhandled type architecture"
#endif

template <>
struct exchange_traits<double>
Expand All @@ -111,6 +140,13 @@ struct exchange_traits<double>
enum { x_type = x_double };
};

template <>
struct exchange_traits<char>
{
typedef basic_type_tag type_family;
enum { x_type = x_char };
};

template <>
struct exchange_traits<std::string>
{
Expand Down
Loading