aboutsummaryrefslogtreecommitdiff
path: root/odb
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2012-09-10 12:12:06 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2012-09-10 12:12:06 +0200
commit866f0ce4fa567db60d46741a5c865cdf2741c619 (patch)
treebee686836227a8d83251d7670a6849c43c432481 /odb
parentb3af5d13db8c29b42436c54abd94b73b7a7f00bd (diff)
Add support for alternative UTF-16 image for TEXT in SQLite
Use it to handle QString and support std::wstring on Windows.
Diffstat (limited to 'odb')
-rw-r--r--odb/sqlite/query.hxx2
-rw-r--r--odb/sqlite/sqlite-types.hxx3
-rw-r--r--odb/sqlite/statement.cxx34
-rw-r--r--odb/sqlite/traits.cxx36
-rw-r--r--odb/sqlite/traits.hxx118
5 files changed, 172 insertions, 21 deletions
diff --git a/odb/sqlite/query.hxx b/odb/sqlite/query.hxx
index 1e8a0a0..5991c51 100644
--- a/odb/sqlite/query.hxx
+++ b/odb/sqlite/query.hxx
@@ -1225,7 +1225,7 @@ namespace odb
virtual void
bind (sqlite::bind* b)
{
- b->type = sqlite::bind::text;
+ b->type = image_traits<T, id_text>::bind_value;
b->buffer = buffer_.data ();
b->size = &size_;
}
diff --git a/odb/sqlite/sqlite-types.hxx b/odb/sqlite/sqlite-types.hxx
index 316c032..295cd1f 100644
--- a/odb/sqlite/sqlite-types.hxx
+++ b/odb/sqlite/sqlite-types.hxx
@@ -22,7 +22,8 @@ namespace odb
{
integer, // Buffer is long long; size, capacity, truncated are unused.
real, // Buffer is double; size, capacity, truncated are unused.
- text, // Buffer is a char array.
+ text, // Buffer is a UTF-8 char array.
+ text16, // Buffer is a UTF-16 2-byte char array (sizes in bytes).
blob // Buffer is a char array.
};
diff --git a/odb/sqlite/statement.cxx b/odb/sqlite/statement.cxx
index 60cf410..36066ff 100644
--- a/odb/sqlite/statement.cxx
+++ b/odb/sqlite/statement.cxx
@@ -125,6 +125,15 @@ namespace odb
SQLITE_STATIC);
break;
}
+ case bind::text16:
+ {
+ e = sqlite3_bind_text16 (stmt_,
+ j,
+ b.buffer,
+ static_cast<int> (*b.size),
+ SQLITE_STATIC);
+ break;
+ }
case bind::blob:
{
e = sqlite3_bind_blob (stmt_,
@@ -189,17 +198,28 @@ namespace odb
break;
}
case bind::text:
+ case bind::text16:
case bind::blob:
{
- // SQLite documentation recommends that we first call *_text()
- // or *_blob() function in order to force the type conversion,
- // if any.
+ // SQLite documentation recommends that we first call *_text(),
+ // *_text16(), or *_blob() function in order to force the type
+ // conversion, if any.
//
- const void* d (b.type == bind::text
- ? sqlite3_column_text (stmt_, j)
- : sqlite3_column_blob (stmt_, j));
+ const void* d;
- *b.size = static_cast<size_t> (sqlite3_column_bytes (stmt_, j));
+ if (b.type != bind::text16)
+ {
+ d = b.type == bind::text
+ ? sqlite3_column_text (stmt_, j)
+ : sqlite3_column_blob (stmt_, j);
+ *b.size = static_cast<size_t> (sqlite3_column_bytes (stmt_, j));
+ }
+ else
+ {
+ d = sqlite3_column_text16 (stmt_, j);
+ *b.size = static_cast<size_t> (
+ sqlite3_column_bytes16 (stmt_, j));
+ }
if (*b.size > b.capacity)
{
diff --git a/odb/sqlite/traits.cxx b/odb/sqlite/traits.cxx
index 0e875a2..3f9c5cb 100644
--- a/odb/sqlite/traits.cxx
+++ b/odb/sqlite/traits.cxx
@@ -46,6 +46,42 @@ namespace odb
memcpy (b.data (), v, n);
}
+#ifdef _WIN32
+ //
+ // default_value_traits<std::wstring>
+ //
+
+ void default_value_traits<wstring, id_text>::
+ set_image (buffer& b, size_t& n, bool& is_null, const wstring& v)
+ {
+ is_null = false;
+ n = v.size () * 2;
+
+ if (n > b.capacity ())
+ b.capacity (n);
+
+ if (n != 0)
+ memcpy (b.data (), v.c_str (), n);
+ }
+
+ //
+ // c_wstring_value_traits
+ //
+
+ void c_wstring_value_traits::
+ set_image (buffer& b, size_t& n, bool& is_null, const wchar_t* v)
+ {
+ is_null = false;
+ n = wcslen (v) * 2;
+
+ if (n > b.capacity ())
+ b.capacity (n);
+
+ if (n != 0)
+ memcpy (b.data (), v, n);
+ }
+#endif // _WIN32
+
//
// default_value_traits<vector<char>, id_blob>
//
diff --git a/odb/sqlite/traits.hxx b/odb/sqlite/traits.hxx
index 65883b6..0de67f9 100644
--- a/odb/sqlite/traits.hxx
+++ b/odb/sqlite/traits.hxx
@@ -20,6 +20,7 @@
#include <odb/details/wrapper-p.hxx>
#include <odb/sqlite/version.hxx>
+#include <odb/sqlite/sqlite-types.hxx>
#include <odb/sqlite/details/export.hxx>
namespace odb
@@ -38,20 +39,27 @@ namespace odb
// image_traits
//
- template <database_type_id>
+ template <typename T, database_type_id>
struct image_traits;
- template <>
- struct image_traits<id_integer> {typedef long long image_type;};
+ template <typename T>
+ struct image_traits<T, id_integer> {typedef long long image_type;};
- template <>
- struct image_traits<id_real> {typedef double image_type;};
+ template <typename T>
+ struct image_traits<T, id_real> {typedef double image_type;};
- template <>
- struct image_traits<id_text> {typedef details::buffer image_type;};
+ template <typename T>
+ struct image_traits<T, id_text>
+ {
+ typedef details::buffer image_type;
- template <>
- struct image_traits<id_blob> {typedef details::buffer image_type;};
+ // By default the text is in UTF-8.
+ //
+ static const bind::buffer_type bind_value = bind::text;
+ };
+
+ template <typename T>
+ struct image_traits<T, id_blob> {typedef details::buffer image_type;};
//
// value_traits
@@ -97,7 +105,7 @@ namespace odb
typedef W value_type;
typedef wrapped_type query_type;
- typedef typename image_traits<ID>::image_type image_type;
+ typedef typename image_traits<wrapped_type, ID>::image_type image_type;
typedef value_traits<wrapped_type, ID> vtraits;
@@ -136,7 +144,7 @@ namespace odb
typedef W value_type;
typedef wrapped_type query_type;
- typedef typename image_traits<ID>::image_type image_type;
+ typedef typename image_traits<wrapped_type, ID>::image_type image_type;
typedef value_traits<wrapped_type, ID> vtraits;
@@ -184,7 +192,7 @@ namespace odb
{
typedef T value_type;
typedef T query_type;
- typedef typename image_traits<ID>::image_type image_type;
+ typedef typename image_traits<T, ID>::image_type image_type;
static void
set_value (T& v, const image_type& i, bool is_null)
@@ -305,6 +313,92 @@ namespace odb
{
};
+#ifdef _WIN32
+ // std::wstring specialization. Using UTF-16 binding.
+ //
+ template <>
+ struct image_traits<std::wstring, id_text>
+ {
+ typedef details::buffer image_type;
+ static const bind::buffer_type bind_value = bind::text16;
+ };
+
+ template <>
+ struct LIBODB_SQLITE_EXPORT default_value_traits<std::wstring, id_text>
+ {
+ typedef std::wstring value_type;
+ typedef std::wstring query_type;
+ typedef details::buffer image_type;
+
+ static void
+ set_value (std::wstring& v,
+ const details::buffer& b,
+ std::size_t n,
+ bool is_null)
+ {
+ if (!is_null)
+ v.assign (reinterpret_cast<const wchar_t*> (b.data ()), n / 2);
+ else
+ v.erase ();
+ }
+
+ static void
+ set_image (details::buffer&,
+ std::size_t& n,
+ bool& is_null,
+ const std::wstring&);
+ };
+
+ // const wchar_t* specialization
+ //
+ template <>
+ struct c_wstring_image_traits
+ {
+ typedef details::buffer image_type;
+ static const bind::buffer_type bind_value = bind::text16;
+ };
+
+ struct LIBODB_SQLITE_EXPORT c_wstring_value_traits
+ {
+ typedef const wchar_t* value_type;
+ typedef const wchar_t* query_type;
+ typedef details::buffer image_type;
+
+ static void
+ set_image (details::buffer&,
+ std::size_t& n,
+ bool& is_null,
+ const wchar_t*);
+ };
+
+ template <>
+ struct image_traits<const wchar_t*, id_text>: c_wstring_image_traits {};
+
+ template <>
+ struct LIBODB_SQLITE_EXPORT default_value_traits<const wchar_t*, id_text>:
+ c_wstring_value_traits
+ {
+ };
+
+ template <std::size_t n>
+ struct image_traits<wchar_t[n], id_text>: c_wstring_image_traits {};
+
+ template <std::size_t n>
+ struct default_value_traits<wchar_t[n], id_text>:
+ c_wstring_value_traits
+ {
+ };
+
+ template <std::size_t n>
+ struct image_traits<const wchar_t[n], id_text>: c_wstring_image_traits {};
+
+ template <std::size_t n>
+ struct default_value_traits<const wchar_t[n], id_text>:
+ c_wstring_value_traits
+ {
+ };
+#endif // _WIN32
+
// std::vector<char> (buffer) specialization.
//
template <>