Skip to content

Commit

Permalink
Add std::wstring support for ODBC backend
Browse files Browse the repository at this point in the history
Handle wide-strings similarly to how normal strings are already handled.

For now support for them is only available in the ODBC backend.

Also add conversion functions between UTF-{8,16,32} and wchar_t and the
tests for them. Note that some of these functions are not used yet, but
provide the complete set as they probably will be in the future.

Co-Authored-By: Vadim Zeitlin <[email protected]>
  • Loading branch information
bold84 and vadz committed Nov 17, 2024
1 parent 55a98cf commit 57d1945
Show file tree
Hide file tree
Showing 29 changed files with 1,669 additions and 4 deletions.
4 changes: 3 additions & 1 deletion docs/api/backend.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Backends reference

This part of the documentation is provided for those who want towrite (and contribute!) their
This part of the documentation is provided for those who want to write (and contribute!) their
own backends. It is anyway recommendedthat authors of new backend see the code of some existing
backend forhints on how things are really done.

Expand Down Expand Up @@ -28,6 +28,7 @@ enum data_type
enum db_type
{
db_string,
db_wstring,
db_int8,
db_uint8,
db_int16,
Expand All @@ -50,6 +51,7 @@ enum exchange_type
{
x_char,
x_stdstring,
x_stdwstring,
x_int8,
x_uint8,
x_int16,
Expand Down
2 changes: 1 addition & 1 deletion docs/api/client.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 db_type { db_string, db_date, db_double, db_int8, db_uint8, db_int16, db_uint16, db_int32, db_uint32, db_int64, db_uint64 };
enum db_type { db_string, db_wstring, 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 };
Expand Down
1 change: 1 addition & 0 deletions docs/backends/odbc.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ For the ODBC backend, this type mapping is:
| SQL_INTEGER | db_int32 | int32_t |
| SQL_BIGINT | db_int64 | int64_t |
| SQL_CHAR, SQL_VARCHAR | db_string | std::string |
| SQL_WCHAR, SQL_WVARCHAR, SQL_WLONGVARCHAR | db_wstring | std::wstring |
| SQL_TYPE_DATE, SQL_TYPE_TIME, SQL_TYPE_TIMESTAMP | db_date | std::tm |

Not all ODBC drivers support all datatypes.
Expand Down
6 changes: 6 additions & 0 deletions include/private/soci-exchange-cast.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ struct exchange_type_traits<x_stdstring>
typedef std::string value_type;
};

template <>
struct exchange_type_traits<x_stdwstring>
{
typedef std::wstring value_type;
};

template <>
struct exchange_type_traits<x_int8>
{
Expand Down
6 changes: 6 additions & 0 deletions include/private/soci-vector-helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ 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_stdwstring:
return exchange_vector_type_cast<x_stdwstring>(data).size();
case x_int8:
return exchange_vector_type_cast<x_int8>(data).size();
case x_uint8:
Expand Down Expand Up @@ -76,6 +78,9 @@ 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_stdwstring:
exchange_vector_type_cast<x_stdwstring>(data).resize(newSize);
return;
case x_int8:
exchange_vector_type_cast<x_int8>(data).resize(newSize);
return;
Expand Down Expand Up @@ -131,6 +136,7 @@ inline std::string& vector_string_value(exchange_type e, void *data, std::size_t
return exchange_vector_type_cast<x_xmltype>(data).at(ind).value;
case x_longstring:
return exchange_vector_type_cast<x_longstring>(data).at(ind).value;
case x_stdwstring:
case x_char:
case x_int8:
case x_uint8:
Expand Down
7 changes: 7 additions & 0 deletions include/soci/exchange-traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,13 @@ struct exchange_traits<std::string>
enum { x_type = x_stdstring };
};

template <>
struct exchange_traits<std::wstring>
{
typedef basic_type_tag type_family;
enum { x_type = x_stdwstring };
};

template <>
struct exchange_traits<std::tm>
{
Expand Down
14 changes: 14 additions & 0 deletions include/soci/odbc/soci-odbc.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ namespace details
{
return reinterpret_cast<SQLCHAR*>(const_cast<char*>(s.c_str()));
}

inline SQLWCHAR* sqlchar_cast(std::wstring const& s)
{
return reinterpret_cast<SQLWCHAR*>(const_cast<wchar_t*>(s.c_str()));
}

inline SQLWCHAR* sqlchar_cast(std::u16string const& s)
{
return reinterpret_cast<SQLWCHAR*>(const_cast<char16_t*>(s.c_str()));
}
}

// Option allowing to specify the "driver completion" parameter of
Expand Down Expand Up @@ -192,6 +202,10 @@ struct odbc_standard_use_type_backend : details::standard_use_type_backend,
SQLSMALLINT& sqlType,
SQLSMALLINT& cType);

void copy_from_string(const std::wstring& s,
SQLLEN& size,
SQLSMALLINT& sqlType,
SQLSMALLINT& cType);
};

struct odbc_vector_use_type_backend : details::vector_use_type_backend,
Expand Down
1 change: 1 addition & 0 deletions include/soci/ref-counted-statement.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "soci/statement.h"
#include "soci/into-type.h"
#include "soci/use-type.h"
#include "soci-unicode.h"
// std
#include <sstream>

Expand Down
5 changes: 5 additions & 0 deletions include/soci/soci-backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ namespace soci
enum db_type
{
db_string,
db_wstring,
db_int8,
db_uint8,
db_int16,
Expand Down Expand Up @@ -61,6 +62,7 @@ enum exchange_type
{
x_char,
x_stdstring,
x_stdwstring,
x_int8,
x_uint8,
x_int16,
Expand Down Expand Up @@ -271,6 +273,9 @@ class statement_backend
case db_uint64: return dt_unsigned_long_long;
case db_blob: return dt_blob;
case db_xml: return dt_xml;

case db_wstring:
throw soci_error("unable to convert value to data_type");
}

// unreachable
Expand Down
Loading

0 comments on commit 57d1945

Please sign in to comment.