From a849d159fd03d3c954df3fc60826680f5d1afd65 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 24 Jan 2013 15:10:21 +0200 Subject: Add support for mapping char[N] to CHAR/VARCHAR database types Also improve query support for arrays (decaying). --- odb/sqlite/query.hxx | 324 +++++++++++++++++++++++++++++++++++++------------- odb/sqlite/query.txx | 10 +- odb/sqlite/traits.cxx | 101 ++++++++++++++-- odb/sqlite/traits.hxx | 255 ++++++++++++++++++++++++++++++++++----- 4 files changed, 569 insertions(+), 121 deletions(-) (limited to 'odb') diff --git a/odb/sqlite/query.hxx b/odb/sqlite/query.hxx index 0f7657c..5ee377f 100644 --- a/odb/sqlite/query.hxx +++ b/odb/sqlite/query.hxx @@ -30,23 +30,72 @@ namespace odb namespace sqlite { template - class val_bind + struct val_bind { - public: + typedef const T& type; + + explicit + val_bind (type v): val (v) {} + + type val; + }; + + template + struct val_bind + { + typedef const T* type; + explicit - val_bind (const T& v): val (v) {} + val_bind (type v): val (v) {} - const T& val; + type val; }; template - class ref_bind + struct ref_bind + { + typedef const T& type; + + explicit + ref_bind (type r): ref (r) {} + + const void* + ptr () const {return &ref;} + + type ref; + }; + + template + struct ref_bind + { + typedef const T* type; + + explicit + ref_bind (type r): ref (r) {} + + // Allow implicit conversion from decayed ref_bind's. + // + ref_bind (ref_bind r): ref (r.ref) {} + ref_bind (ref_bind r): ref (r.ref) {} + + const void* + ptr () const {return ref;} + + type ref; + }; + + template + struct val_bind_typed: val_bind { - public: explicit - ref_bind (const T& r): ref (r) {} + val_bind_typed (typename val_bind::type v): val_bind (v) {} + }; - const T& ref; + template + struct ref_bind_typed: ref_bind + { + explicit + ref_bind_typed (typename ref_bind::type r): ref_bind (r) {} }; struct LIBODB_SQLITE_EXPORT query_param: details::shared_base @@ -178,8 +227,15 @@ namespace odb query_base (val_bind v) : parameters_ (new (details::shared) query_params) { - append::db_type_id> ( - v, details::conversion::to ()); + *this += v; + } + + template + explicit + query_base (val_bind_typed v) + : parameters_ (new (details::shared) query_params) + { + *this += v; } template @@ -187,8 +243,15 @@ namespace odb query_base (ref_bind r) : parameters_ (new (details::shared) query_params) { - append::db_type_id> ( - r, details::conversion::to ()); + *this += r; + } + + template + explicit + query_base (ref_bind_typed r) + : parameters_ (new (details::shared) query_params) + { + *this += r; } template @@ -252,6 +315,13 @@ namespace odb return val_bind (x); } + template + static val_bind_typed + _val (const T& x) + { + return val_bind_typed (x); + } + template static ref_bind _ref (const T& x) @@ -259,6 +329,13 @@ namespace odb return ref_bind (x); } + template + static ref_bind_typed + _ref (const T& x) + { + return ref_bind_typed (x); + } + public: query_base& operator+= (const query_base&); @@ -279,6 +356,17 @@ namespace odb return *this; } + template + query_base& + operator+= (val_bind_typed v) + { + // We are not using default type_traits so no default conversion + // either. + // + append (v, 0); + return *this; + } + template query_base& operator+= (ref_bind r) @@ -288,6 +376,17 @@ namespace odb return *this; } + template + query_base& + operator+= (ref_bind_typed r) + { + // We are not using default type_traits so no default conversion + // either. + // + append (r, 0); + return *this; + } + // Implementation details. // public: @@ -346,16 +445,26 @@ namespace odb template inline query_base - operator+ (const query_base& q, ref_bind b) + operator+ (val_bind b, const query_base& q) + { + query_base r; + r += b; + r += q; + return r; + } + + template + inline query_base + operator+ (const query_base& q, val_bind_typed b) { query_base r (q); r += b; return r; } - template + template inline query_base - operator+ (val_bind b, const query_base& q) + operator+ (val_bind_typed b, const query_base& q) { query_base r; r += b; @@ -365,6 +474,15 @@ namespace odb template inline query_base + operator+ (const query_base& q, ref_bind b) + { + query_base r (q); + r += b; + return r; + } + + template + inline query_base operator+ (ref_bind b, const query_base& q) { query_base r; @@ -373,6 +491,25 @@ namespace odb return r; } + template + inline query_base + operator+ (const query_base& q, ref_bind_typed b) + { + query_base r (q); + r += b; + return r; + } + + template + inline query_base + operator+ (ref_bind_typed b, const query_base& q) + { + query_base r; + r += b; + r += q; + return r; + } + inline query_base operator+ (const query_base& q, const std::string& s) { @@ -400,16 +537,26 @@ namespace odb template inline query_base - operator+ (const std::string& s, ref_bind b) + operator+ (val_bind b, const std::string& s) + { + query_base r; + r += b; + r += s; + return r; + } + + template + inline query_base + operator+ (const std::string& s, val_bind_typed b) { query_base r (s); r += b; return r; } - template + template inline query_base - operator+ (val_bind b, const std::string& s) + operator+ (val_bind_typed b, const std::string& s) { query_base r; r += b; @@ -419,6 +566,15 @@ namespace odb template inline query_base + operator+ (const std::string& s, ref_bind b) + { + query_base r (s); + r += b; + return r; + } + + template + inline query_base operator+ (ref_bind b, const std::string& s) { query_base r; @@ -427,6 +583,25 @@ namespace odb return r; } + template + inline query_base + operator+ (const std::string& s, ref_bind_typed b) + { + query_base r (s); + r += b; + return r; + } + + template + inline query_base + operator+ (ref_bind_typed b, const std::string& s) + { + query_base r; + r += b; + r += s; + return r; + } + LIBODB_SQLITE_EXPORT query_base operator&& (const query_base&, const query_base&); @@ -476,23 +651,11 @@ namespace odb const char* conversion_; }; - template - class copy_bind: public val_bind - { - public: - explicit - copy_bind (const T2& v): val_bind (val), val (v) {} - - const T val; - }; - - template - const T& - type_instance (); - template struct query_column: query_column_base { + typedef typename decay_traits::type decayed_type; + // Note that we keep shallow copies of the table, column, and conversion // expression. The latter can be NULL. // @@ -527,16 +690,17 @@ namespace odb // public: query_base - in (const T&, const T&) const; + in (decayed_type, decayed_type) const; query_base - in (const T&, const T&, const T&) const; + in (decayed_type, decayed_type, decayed_type) const; query_base - in (const T&, const T&, const T&, const T&) const; + in (decayed_type, decayed_type, decayed_type, decayed_type) const; query_base - in (const T&, const T&, const T&, const T&, const T&) const; + in (decayed_type, decayed_type, decayed_type, decayed_type, + decayed_type) const; template query_base @@ -546,7 +710,7 @@ namespace odb // public: query_base - equal (const T& v) const + equal (decayed_type v) const { return equal (val_bind (v)); } @@ -564,8 +728,7 @@ namespace odb query_base equal (val_bind v) const { - copy_bind c (v.val); - return equal (c); + return equal (val_bind (decayed_type (v.val))); } query_base @@ -578,13 +741,13 @@ namespace odb } friend query_base - operator== (const query_column& c, const T& v) + operator== (const query_column& c, decayed_type v) { return c.equal (v); } friend query_base - operator== (const T& v, const query_column& c) + operator== (decayed_type v, const query_column& c) { return c.equal (v); } @@ -631,7 +794,7 @@ namespace odb // public: query_base - unequal (const T& v) const + unequal (decayed_type v) const { return unequal (val_bind (v)); } @@ -649,8 +812,7 @@ namespace odb query_base unequal (val_bind v) const { - copy_bind c (v.val); - return unequal (c); + return unequal (val_bind (decayed_type (v.val))); } query_base @@ -663,13 +825,13 @@ namespace odb } friend query_base - operator!= (const query_column& c, const T& v) + operator!= (const query_column& c, decayed_type v) { return c.unequal (v); } friend query_base - operator!= (const T& v, const query_column& c) + operator!= (decayed_type v, const query_column& c) { return c.unequal (v); } @@ -716,7 +878,7 @@ namespace odb // public: query_base - less (const T& v) const + less (decayed_type v) const { return less (val_bind (v)); } @@ -734,8 +896,7 @@ namespace odb query_base less (val_bind v) const { - copy_bind c (v.val); - return less (c); + return less (val_bind (decayed_type (v.val))); } query_base @@ -748,13 +909,13 @@ namespace odb } friend query_base - operator< (const query_column& c, const T& v) + operator< (const query_column& c, decayed_type v) { return c.less (v); } friend query_base - operator< (const T& v, const query_column& c) + operator< (decayed_type v, const query_column& c) { return c.greater (v); } @@ -801,7 +962,7 @@ namespace odb // public: query_base - greater (const T& v) const + greater (decayed_type v) const { return greater (val_bind (v)); } @@ -819,8 +980,7 @@ namespace odb query_base greater (val_bind v) const { - copy_bind c (v.val); - return greater (c); + return greater (val_bind (decayed_type (v.val))); } query_base @@ -833,13 +993,13 @@ namespace odb } friend query_base - operator> (const query_column& c, const T& v) + operator> (const query_column& c, decayed_type v) { return c.greater (v); } friend query_base - operator> (const T& v, const query_column& c) + operator> (decayed_type v, const query_column& c) { return c.less (v); } @@ -886,7 +1046,7 @@ namespace odb // public: query_base - less_equal (const T& v) const + less_equal (decayed_type v) const { return less_equal (val_bind (v)); } @@ -904,8 +1064,7 @@ namespace odb query_base less_equal (val_bind v) const { - copy_bind c (v.val); - return less_equal (c); + return less_equal (val_bind (decayed_type (v.val))); } query_base @@ -918,13 +1077,13 @@ namespace odb } friend query_base - operator<= (const query_column& c, const T& v) + operator<= (const query_column& c, decayed_type v) { return c.less_equal (v); } friend query_base - operator<= (const T& v, const query_column& c) + operator<= (decayed_type v, const query_column& c) { return c.greater_equal (v); } @@ -971,7 +1130,7 @@ namespace odb // public: query_base - greater_equal (const T& v) const + greater_equal (decayed_type v) const { return greater_equal (val_bind (v)); } @@ -989,8 +1148,7 @@ namespace odb query_base greater_equal (val_bind v) const { - copy_bind c (v.val); - return greater_equal (c); + return greater_equal (val_bind (decayed_type (v.val))); } query_base @@ -1003,13 +1161,13 @@ namespace odb } friend query_base - operator>= (const query_column& c, const T& v) + operator>= (const query_column& c, decayed_type v) { return c.greater_equal (v); } friend query_base - operator>= (const T& v, const query_column& c) + operator>= (decayed_type v, const query_column& c) { return c.less_equal (v); } @@ -1061,7 +1219,8 @@ namespace odb { // We can compare columns only if we can compare their C++ types. // - (void) (sizeof (type_instance () == type_instance ())); + (void) (sizeof (decay_traits::instance () == + decay_traits::instance ())); query_base q (table_, column_); q += "="; @@ -1075,7 +1234,8 @@ namespace odb { // We can compare columns only if we can compare their C++ types. // - (void) (sizeof (type_instance () != type_instance ())); + (void) (sizeof (decay_traits::instance () != + decay_traits::instance ())); query_base q (table_, column_); q += "!="; @@ -1089,7 +1249,8 @@ namespace odb { // We can compare columns only if we can compare their C++ types. // - (void) (sizeof (type_instance () < type_instance ())); + (void) (sizeof (decay_traits::instance () < + decay_traits::instance ())); query_base q (table_, column_); q += "<"; @@ -1103,7 +1264,8 @@ namespace odb { // We can compare columns only if we can compare their C++ types. // - (void) (sizeof (type_instance () > type_instance ())); + (void) (sizeof (decay_traits::instance () > + decay_traits::instance ())); query_base q (table_, column_); q += ">"; @@ -1117,7 +1279,8 @@ namespace odb { // We can compare columns only if we can compare their C++ types. // - (void) (sizeof (type_instance () <= type_instance ())); + (void) (sizeof (decay_traits::instance () <= + decay_traits::instance ())); query_base q (table_, column_); q += "<="; @@ -1131,7 +1294,8 @@ namespace odb { // We can compare columns only if we can compare their C++ types. // - (void) (sizeof (type_instance () >= type_instance ())); + (void) (sizeof (decay_traits::instance () >= + decay_traits::instance ())); query_base q (table_, column_); q += ">="; @@ -1189,7 +1353,7 @@ namespace odb template struct query_param_impl: query_param { - query_param_impl (ref_bind r) : query_param (&r.ref) {} + query_param_impl (ref_bind r) : query_param (r.ptr ()) {} query_param_impl (val_bind v) : query_param (0) {init (v.val);} virtual bool @@ -1208,7 +1372,7 @@ namespace odb private: void - init (const T& v) + init (typename decay_traits::type v) { bool is_null (false); // Can't be NULL. value_traits::set_image (image_, is_null, v); @@ -1223,7 +1387,7 @@ namespace odb template struct query_param_impl: query_param { - query_param_impl (ref_bind r) : query_param (&r.ref) {} + query_param_impl (ref_bind r) : query_param (r.ptr ()) {} query_param_impl (val_bind v) : query_param (0) {init (v.val);} virtual bool @@ -1242,7 +1406,7 @@ namespace odb private: void - init (const T& v) + init (typename decay_traits::type v) { bool is_null (false); // Can't be NULL. value_traits::set_image (image_, is_null, v); @@ -1257,7 +1421,7 @@ namespace odb template struct query_param_impl: query_param { - query_param_impl (ref_bind r) : query_param (&r.ref) {} + query_param_impl (ref_bind r) : query_param (r.ptr ()) {} query_param_impl (val_bind v) : query_param (0) {init (v.val);} virtual bool @@ -1276,7 +1440,7 @@ namespace odb private: bool - init (const T& v) + init (typename decay_traits::type v) { bool is_null (false); // Can't be NULL. std::size_t cap (buffer_.capacity ()); @@ -1294,7 +1458,7 @@ namespace odb template struct query_param_impl: query_param { - query_param_impl (ref_bind r) : query_param (&r.ref) {} + query_param_impl (ref_bind r) : query_param (r.ptr ()) {} query_param_impl (val_bind v) : query_param (0) {init (v.val);} virtual bool @@ -1313,7 +1477,7 @@ namespace odb private: bool - init (const T& v) + init (typename decay_traits::type v) { bool is_null (false); // Can't be NULL. std::size_t cap (buffer_.capacity ()); diff --git a/odb/sqlite/query.txx b/odb/sqlite/query.txx index f719ece..7342187 100644 --- a/odb/sqlite/query.txx +++ b/odb/sqlite/query.txx @@ -26,7 +26,7 @@ namespace odb // template query_base query_column:: - in (const T& v1, const T& v2) const + in (decayed_type v1, decayed_type v2) const { query_base q (table_, column_); q += "IN ("; @@ -39,7 +39,7 @@ namespace odb template query_base query_column:: - in (const T& v1, const T& v2, const T& v3) const + in (decayed_type v1, decayed_type v2, decayed_type v3) const { query_base q (table_, column_); q += "IN ("; @@ -54,7 +54,8 @@ namespace odb template query_base query_column:: - in (const T& v1, const T& v2, const T& v3, const T& v4) const + in (decayed_type v1, decayed_type v2, decayed_type v3, + decayed_type v4) const { query_base q (table_, column_); q += "IN ("; @@ -71,7 +72,8 @@ namespace odb template query_base query_column:: - in (const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) const + in (decayed_type v1, decayed_type v2, decayed_type v3, decayed_type v4, + decayed_type v5) const { query_base q (table_, column_); q += "IN ("; diff --git a/odb/sqlite/traits.cxx b/odb/sqlite/traits.cxx index 3f9c5cb..753c181 100644 --- a/odb/sqlite/traits.cxx +++ b/odb/sqlite/traits.cxx @@ -15,7 +15,6 @@ namespace odb // // default_value_traits // - void default_value_traits:: set_image (buffer& b, size_t& n, bool& is_null, const string& v) { @@ -32,7 +31,6 @@ namespace odb // // c_string_value_traits // - void c_string_value_traits:: set_image (buffer& b, size_t& n, bool& is_null, const char* v) { @@ -46,11 +44,55 @@ namespace odb memcpy (b.data (), v, n); } -#ifdef _WIN32 // - // default_value_traits + // c_array_value_traits_base // + void c_array_value_traits_base:: + set_value (char* const& v, + const details::buffer& b, + size_t n, + bool is_null, + size_t N) + { + if (!is_null) + { + n = n < N ? n : N; + + if (n != 0) + memcpy (v, b.data (), n); + } + else + n = 0; + + if (n != N) // Append '\0' if there is space. + v[n] = '\0'; + } + void c_array_value_traits_base:: + set_image (details::buffer& b, + size_t& n, + bool& is_null, + const char* v, + size_t N) + { + is_null = false; + + // Figure out the length. We cannot use strlen since it may + // not be 0-terminated (strnlen is not standard). + // + for (n = 0; n != N && v[n] != '\0'; ++n); + + if (n > b.capacity ()) + b.capacity (n); + + if (n != 0) + memcpy (b.data (), v, n); + } + + // + // default_value_traits + // +#ifdef _WIN32 void default_value_traits:: set_image (buffer& b, size_t& n, bool& is_null, const wstring& v) { @@ -67,7 +109,6 @@ namespace odb // // c_wstring_value_traits // - void c_wstring_value_traits:: set_image (buffer& b, size_t& n, bool& is_null, const wchar_t* v) { @@ -80,12 +121,59 @@ namespace odb if (n != 0) memcpy (b.data (), v, n); } + + // + // c_warray_value_traits_base + // + void c_warray_value_traits_base:: + set_value (wchar_t* const& v, + const details::buffer& b, + size_t n, + bool is_null, + size_t N) + { + if (!is_null) + { + n /= 2; + n = n < N ? n : N; + + if (n != 0) + memcpy (v, b.data (), n * sizeof (wchar_t)); + } + else + n = 0; + + if (n != N) // Append '\0' if there is space. + v[n] = L'\0'; + } + + void c_warray_value_traits_base:: + set_image (details::buffer& b, + size_t& n, + bool& is_null, + const wchar_t* v, + size_t N) + { + is_null = false; + + // Figure out the length. We cannot use wcslen since it may + // not be 0-terminated (wcsnlen is not standard). + // + for (n = 0; n != N && v[n] != L'\0'; ++n); + + n *= 2; + + if (n > b.capacity ()) + b.capacity (n); + + if (n != 0) + memcpy (b.data (), v, n); + } #endif // _WIN32 // // default_value_traits, id_blob> // - void default_value_traits, id_blob>:: set_image (details::buffer& b, size_t& n, @@ -107,7 +195,6 @@ namespace odb // // default_value_traits, id_blob> // - void default_value_traits, id_blob>:: set_image (details::buffer& b, size_t& n, diff --git a/odb/sqlite/traits.hxx b/odb/sqlite/traits.hxx index e6abf2d..0cdf171 100644 --- a/odb/sqlite/traits.hxx +++ b/odb/sqlite/traits.hxx @@ -284,7 +284,7 @@ namespace odb const std::string&); }; - // const char* specialization + // char*/const char* specialization // // Specialization for const char* which only supports initialization // of an image from the value but not the other way around. This way @@ -303,35 +303,129 @@ namespace odb }; template <> + struct LIBODB_SQLITE_EXPORT default_value_traits: + c_string_value_traits {}; + + template <> struct LIBODB_SQLITE_EXPORT default_value_traits: - c_string_value_traits + c_string_value_traits {}; + + // char[N] specialization. + // + struct LIBODB_SQLITE_EXPORT c_array_value_traits_base { - typedef const char* query_type; + static void + set_value (char* const& v, + const details::buffer& b, + std::size_t n, + bool is_null, + std::size_t N); + + static void + set_image (details::buffer& b, + std::size_t& n, + bool& is_null, + const char* v, + std::size_t N); }; template - struct default_value_traits: c_string_value_traits + struct default_value_traits { + typedef char* value_type; typedef char query_type[N]; + typedef details::buffer image_type; + + static void + set_value (char* const& v, + const details::buffer& b, + std::size_t n, + bool is_null) + { + c_array_value_traits_base::set_value (v, b, n, is_null, N); + } + + static void + set_image (details::buffer& b, + std::size_t& n, + bool& is_null, + const char* v) + { + c_array_value_traits_base::set_image (b, n, is_null, v, N); + } }; + // std::array (string) specialization. + // +#ifdef ODB_CXX11 template - struct default_value_traits: c_string_value_traits + struct default_value_traits, id_text> { - typedef const char query_type[N]; + typedef std::array value_type; + typedef std::array query_type; + typedef details::buffer image_type; + + static void + set_value (value_type& v, + const details::buffer& b, + std::size_t n, + bool is_null) + { + c_array_value_traits_base::set_value (v.data (), b, n, is_null, N); + } + + static void + set_image (details::buffer& b, + std::size_t& n, + bool& is_null, + const value_type& v) + { + c_array_value_traits_base::set_image (b, n, is_null, v.data (), N); + } + }; +#endif + + // char specialization. + // + template <> + struct LIBODB_SQLITE_EXPORT default_value_traits + { + typedef char value_type; + typedef char query_type; + typedef details::buffer image_type; + + static void + set_value (char& v, + const details::buffer& b, + std::size_t n, + bool is_null) + { + c_array_value_traits_base::set_value (&v, b, n, is_null, 1); + } + + static void + set_image (details::buffer& b, + std::size_t& n, + bool& is_null, + char v) + { + c_array_value_traits_base::set_image (b, n, is_null, &v, 1); + } }; #ifdef _WIN32 // std::wstring specialization. Using UTF-16 binding. // - template <> - struct image_traits + struct wstring_image_traits { typedef details::buffer image_type; static const bind::buffer_type bind_value = bind::text16; }; template <> + struct image_traits: wstring_image_traits {}; + + template <> struct LIBODB_SQLITE_EXPORT default_value_traits { typedef std::wstring value_type; @@ -357,14 +451,8 @@ namespace odb const std::wstring&); }; - // const wchar_t* specialization + // wchar_t*/const wchar_t* specialization. // - 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; @@ -378,33 +466,130 @@ namespace odb }; template <> - struct image_traits: c_wstring_image_traits {}; + struct image_traits: wstring_image_traits {}; + + template <> + struct LIBODB_SQLITE_EXPORT default_value_traits: + c_wstring_value_traits {}; + + template <> + struct image_traits: wstring_image_traits {}; template <> struct LIBODB_SQLITE_EXPORT default_value_traits: - c_wstring_value_traits + c_wstring_value_traits {}; + + // wchar_t[N] specialization. + // + struct LIBODB_SQLITE_EXPORT c_warray_value_traits_base { - typedef const wchar_t* query_type; + static void + set_value (wchar_t* const& v, + const details::buffer& b, + std::size_t n, + bool is_null, + std::size_t N); + + static void + set_image (details::buffer& b, + std::size_t& n, + bool& is_null, + const wchar_t* v, + std::size_t N); }; template - struct image_traits: c_wstring_image_traits {}; + struct image_traits: wstring_image_traits {}; template - struct default_value_traits: - c_wstring_value_traits + struct default_value_traits { + typedef wchar_t* value_type; typedef wchar_t query_type[N]; + typedef details::buffer image_type; + + static void + set_value (wchar_t* const& v, + const details::buffer& b, + std::size_t n, + bool is_null) + { + c_warray_value_traits_base::set_value (v, b, n, is_null, N); + } + + static void + set_image (details::buffer& b, + std::size_t& n, + bool& is_null, + const wchar_t* v) + { + c_warray_value_traits_base::set_image (b, n, is_null, v, N); + } }; + // std::array (string) specialization. + // +#ifdef ODB_CXX11 template - struct image_traits: c_wstring_image_traits {}; + struct image_traits, id_text>: + wstring_image_traits {}; template - struct default_value_traits: - c_wstring_value_traits + struct default_value_traits, id_text> + { + typedef std::array value_type; + typedef std::array query_type; + typedef details::buffer image_type; + + static void + set_value (value_type& v, + const details::buffer& b, + std::size_t n, + bool is_null) + { + c_warray_value_traits_base::set_value (v.data (), b, n, is_null, N); + } + + static void + set_image (details::buffer& b, + std::size_t& n, + bool& is_null, + const value_type& v) + { + c_warray_value_traits_base::set_image (b, n, is_null, v.data (), N); + } + }; +#endif + + // wchar_t specialization. + // + template <> + struct image_traits: wstring_image_traits {}; + + template <> + struct LIBODB_SQLITE_EXPORT default_value_traits { - typedef const wchar_t query_type[N]; + typedef wchar_t value_type; + typedef wchar_t query_type; + typedef details::buffer image_type; + + static void + set_value (wchar_t& v, + const details::buffer& b, + std::size_t n, + bool is_null) + { + c_warray_value_traits_base::set_value (&v, b, n, is_null, 1); + } + + static void + set_image (details::buffer& b, + std::size_t& n, + bool& is_null, + wchar_t v) + { + c_warray_value_traits_base::set_image (b, n, is_null, &v, 1); + } }; #endif // _WIN32 @@ -634,9 +819,7 @@ namespace odb struct default_type_traits; template - class type_traits: public default_type_traits - { - }; + class type_traits: public default_type_traits {}; // Integral types. // @@ -729,6 +912,12 @@ namespace odb }; template <> + struct default_type_traits + { + static const database_type_id db_type_id = id_text; + }; + + template <> struct default_type_traits { static const database_type_id db_type_id = id_text; @@ -740,14 +929,20 @@ namespace odb static const database_type_id db_type_id = id_text; }; - template - struct default_type_traits + template <> + struct default_type_traits { static const database_type_id db_type_id = id_text; }; // Binary types. // + template + struct default_type_traits + { + static const database_type_id db_type_id = id_blob; + }; + template <> struct default_type_traits > { -- cgit v1.1