diff options
-rw-r--r-- | odb/pgsql/query.hxx | 368 | ||||
-rw-r--r-- | odb/pgsql/query.txx | 10 | ||||
-rw-r--r-- | odb/pgsql/traits.cxx | 49 | ||||
-rw-r--r-- | odb/pgsql/traits.hxx | 121 |
4 files changed, 429 insertions, 119 deletions
diff --git a/odb/pgsql/query.hxx b/odb/pgsql/query.hxx index 9d0b333..5acf24e 100644 --- a/odb/pgsql/query.hxx +++ b/odb/pgsql/query.hxx @@ -31,23 +31,72 @@ namespace odb namespace pgsql { template <typename T> - class val_bind + struct val_bind { - public: + typedef const T& type; + + explicit + val_bind (type v): val (v) {} + + type val; + }; + + template <typename T, std::size_t N> + struct val_bind<T[N]> + { + typedef const T* type; + explicit - val_bind (const T& v): val (v) {} + val_bind (type v): val (v) {} - const T& val; + type val; }; template <typename T> - 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 <typename T, std::size_t N> + struct ref_bind<T[N]> + { + typedef const T* type; + + explicit + ref_bind (type r): ref (r) {} + + // Allow implicit conversion from decayed ref_bind's. + // + ref_bind (ref_bind<T*> r): ref (r.ref) {} + ref_bind (ref_bind<const T*> r): ref (r.ref) {} + + const void* + ptr () const {return ref;} + + type ref; + }; + + template <typename T, database_type_id ID> + struct val_bind_typed: val_bind<T> { - public: explicit - ref_bind (const T& r): ref (r) {} + val_bind_typed (typename val_bind<T>::type v): val_bind<T> (v) {} + }; - const T& ref; + template <typename T, database_type_id ID> + struct ref_bind_typed: ref_bind<T> + { + explicit + ref_bind_typed (typename ref_bind<T>::type r): ref_bind<T> (r) {} }; struct LIBODB_PGSQL_EXPORT query_param: details::shared_base @@ -148,8 +197,15 @@ namespace odb query_base (val_bind<T> v) : binding_ (0, 0), native_binding_ (0, 0, 0, 0) { - append<T, type_traits<T>::db_type_id> ( - v, details::conversion<T>::to ()); + *this += v; + } + + template <typename T, database_type_id ID> + explicit + query_base (val_bind_typed<T, ID> v) + : binding_ (0, 0), native_binding_ (0, 0, 0, 0) + { + *this += v; } template <typename T> @@ -157,8 +213,15 @@ namespace odb query_base (ref_bind<T> r) : binding_ (0, 0), native_binding_ (0, 0, 0, 0) { - append<T, type_traits<T>::db_type_id> ( - r, details::conversion<T>::to ()); + *this += r; + } + + template <typename T, database_type_id ID> + explicit + query_base (ref_bind_typed<T, ID> r) + : binding_ (0, 0), native_binding_ (0, 0, 0, 0) + { + *this += r; } template <database_type_id ID> @@ -231,6 +294,13 @@ namespace odb return val_bind<T> (x); } + template <database_type_id ID, typename T> + static val_bind_typed<T, ID> + _val (const T& x) + { + return val_bind_typed<T, ID> (x); + } + template <typename T> static ref_bind<T> _ref (const T& x) @@ -238,6 +308,13 @@ namespace odb return ref_bind<T> (x); } + template <database_type_id ID, typename T> + static ref_bind_typed<T, ID> + _ref (const T& x) + { + return ref_bind_typed<T, ID> (x); + } + public: query_base& operator+= (const query_base&); @@ -258,6 +335,17 @@ namespace odb return *this; } + template <typename T, database_type_id ID> + query_base& + operator+= (val_bind_typed<T, ID> v) + { + // We are not using default type_traits so no default conversion + // either. + // + append<T, ID> (v, 0); + return *this; + } + template <typename T> query_base& operator+= (ref_bind<T> r) @@ -267,6 +355,17 @@ namespace odb return *this; } + template <typename T, database_type_id ID> + query_base& + operator+= (ref_bind_typed<T, ID> r) + { + // We are not using default type_traits so no default conversion + // either. + // + append<T, ID> (r, 0); + return *this; + } + // Implementation details. // public: @@ -335,16 +434,26 @@ namespace odb template <typename T> inline query_base - operator+ (const query_base& q, ref_bind<T> b) + operator+ (val_bind<T> b, const query_base& q) + { + query_base r; + r += b; + r += q; + return r; + } + + template <typename T, database_type_id ID> + inline query_base + operator+ (const query_base& q, val_bind_typed<T, ID> b) { query_base r (q); r += b; return r; } - template <typename T> + template <typename T, database_type_id ID> inline query_base - operator+ (val_bind<T> b, const query_base& q) + operator+ (val_bind_typed<T, ID> b, const query_base& q) { query_base r; r += b; @@ -354,6 +463,15 @@ namespace odb template <typename T> inline query_base + operator+ (const query_base& q, ref_bind<T> b) + { + query_base r (q); + r += b; + return r; + } + + template <typename T> + inline query_base operator+ (ref_bind<T> b, const query_base& q) { query_base r; @@ -362,6 +480,25 @@ namespace odb return r; } + template <typename T, database_type_id ID> + inline query_base + operator+ (const query_base& q, ref_bind_typed<T, ID> b) + { + query_base r (q); + r += b; + return r; + } + + template <typename T, database_type_id ID> + inline query_base + operator+ (ref_bind_typed<T, ID> 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) { @@ -389,16 +526,26 @@ namespace odb template <typename T> inline query_base - operator+ (const std::string& s, ref_bind<T> b) + operator+ (val_bind<T> b, const std::string& s) + { + query_base r; + r += b; + r += s; + return r; + } + + template <typename T, database_type_id ID> + inline query_base + operator+ (const std::string& s, val_bind_typed<T, ID> b) { query_base r (s); r += b; return r; } - template <typename T> + template <typename T, database_type_id ID> inline query_base - operator+ (val_bind<T> b, const std::string& s) + operator+ (val_bind_typed<T, ID> b, const std::string& s) { query_base r; r += b; @@ -408,6 +555,15 @@ namespace odb template <typename T> inline query_base + operator+ (const std::string& s, ref_bind<T> b) + { + query_base r (s); + r += b; + return r; + } + + template <typename T> + inline query_base operator+ (ref_bind<T> b, const std::string& s) { query_base r; @@ -416,6 +572,25 @@ namespace odb return r; } + template <typename T, database_type_id ID> + inline query_base + operator+ (const std::string& s, ref_bind_typed<T, ID> b) + { + query_base r (s); + r += b; + return r; + } + + template <typename T, database_type_id ID> + inline query_base + operator+ (ref_bind_typed<T, ID> b, const std::string& s) + { + query_base r; + r += b; + r += s; + return r; + } + LIBODB_PGSQL_EXPORT query_base operator&& (const query_base&, const query_base&); @@ -465,23 +640,11 @@ namespace odb const char* conversion_; }; - template <typename T, typename T2> - class copy_bind: public val_bind<T> - { - public: - explicit - copy_bind (const T2& v): val_bind<T> (val), val (v) {} - - const T val; - }; - - template <typename T> - const T& - type_instance (); - template <typename T, database_type_id ID> struct query_column: query_column_base { + typedef typename decay_traits<T>::type decayed_type; + // Note that we keep shallow copies of the table, column, and conversion // expression. The latter can be NULL. // @@ -516,16 +679,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 <typename I> query_base @@ -535,7 +699,7 @@ namespace odb // public: query_base - equal (const T& v) const + equal (decayed_type v) const { return equal (val_bind<T> (v)); } @@ -553,8 +717,7 @@ namespace odb query_base equal (val_bind<T2> v) const { - copy_bind<T, T2> c (v.val); - return equal (c); + return equal (val_bind<T> (decayed_type (v.val))); } query_base @@ -567,13 +730,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); } @@ -620,7 +783,7 @@ namespace odb // public: query_base - unequal (const T& v) const + unequal (decayed_type v) const { return unequal (val_bind<T> (v)); } @@ -638,8 +801,7 @@ namespace odb query_base unequal (val_bind<T2> v) const { - copy_bind<T, T2> c (v.val); - return unequal (c); + return unequal (val_bind<T> (decayed_type (v.val))); } query_base @@ -652,13 +814,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); } @@ -705,7 +867,7 @@ namespace odb // public: query_base - less (const T& v) const + less (decayed_type v) const { return less (val_bind<T> (v)); } @@ -723,8 +885,7 @@ namespace odb query_base less (val_bind<T2> v) const { - copy_bind<T, T2> c (v.val); - return less (c); + return less (val_bind<T> (decayed_type (v.val))); } query_base @@ -737,13 +898,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); } @@ -790,7 +951,7 @@ namespace odb // public: query_base - greater (const T& v) const + greater (decayed_type v) const { return greater (val_bind<T> (v)); } @@ -808,8 +969,7 @@ namespace odb query_base greater (val_bind<T2> v) const { - copy_bind<T, T2> c (v.val); - return greater (c); + return greater (val_bind<T> (decayed_type (v.val))); } query_base @@ -822,13 +982,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); } @@ -875,7 +1035,7 @@ namespace odb // public: query_base - less_equal (const T& v) const + less_equal (decayed_type v) const { return less_equal (val_bind<T> (v)); } @@ -893,8 +1053,7 @@ namespace odb query_base less_equal (val_bind<T2> v) const { - copy_bind<T, T2> c (v.val); - return less_equal (c); + return less_equal (val_bind<T> (decayed_type (v.val)));; } query_base @@ -907,13 +1066,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); } @@ -960,7 +1119,7 @@ namespace odb // public: query_base - greater_equal (const T& v) const + greater_equal (decayed_type v) const { return greater_equal (val_bind<T> (v)); } @@ -978,8 +1137,7 @@ namespace odb query_base greater_equal (val_bind<T2> v) const { - copy_bind<T, T2> c (v.val); - return greater_equal (c); + return greater_equal (val_bind<T> (decayed_type (v.val)));; } query_base @@ -992,13 +1150,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); } @@ -1050,7 +1208,8 @@ namespace odb { // We can compare columns only if we can compare their C++ types. // - (void) (sizeof (type_instance<T> () == type_instance<T2> ())); + (void) (sizeof (decay_traits<T>::instance () == + decay_traits<T2>::instance ())); query_base q (table_, column_); q += "="; @@ -1064,7 +1223,8 @@ namespace odb { // We can compare columns only if we can compare their C++ types. // - (void) (sizeof (type_instance<T> () != type_instance<T2> ())); + (void) (sizeof (decay_traits<T>::instance () != + decay_traits<T2>::instance ())); query_base q (table_, column_); q += "!="; @@ -1078,7 +1238,8 @@ namespace odb { // We can compare columns only if we can compare their C++ types. // - (void) (sizeof (type_instance<T> () < type_instance<T2> ())); + (void) (sizeof (decay_traits<T>::instance () < + decay_traits<T2>::instance ())); query_base q (table_, column_); q += "<"; @@ -1092,7 +1253,8 @@ namespace odb { // We can compare columns only if we can compare their C++ types. // - (void) (sizeof (type_instance<T> () > type_instance<T2> ())); + (void) (sizeof (decay_traits<T>::instance () > + decay_traits<T2>::instance ())); query_base q (table_, column_); q += ">"; @@ -1106,7 +1268,8 @@ namespace odb { // We can compare columns only if we can compare their C++ types. // - (void) (sizeof (type_instance<T> () <= type_instance<T2> ())); + (void) (sizeof (decay_traits<T>::instance () <= + decay_traits<T2>::instance ())); query_base q (table_, column_); q += "<="; @@ -1120,7 +1283,8 @@ namespace odb { // We can compare columns only if we can compare their C++ types. // - (void) (sizeof (type_instance<T> () >= type_instance<T2> ())); + (void) (sizeof (decay_traits<T>::instance () >= + decay_traits<T2>::instance ())); query_base q (table_, column_); q += ">="; @@ -1178,7 +1342,7 @@ namespace odb template <typename T> struct query_param_impl<T, id_boolean>: query_param { - query_param_impl (ref_bind<T> r) : query_param (&r.ref) {} + query_param_impl (ref_bind<T> r) : query_param (r.ptr ()) {} query_param_impl (val_bind<T> v) : query_param (0) {init (v.val);} virtual bool @@ -1203,7 +1367,7 @@ namespace odb private: void - init (const T& v) + init (typename decay_traits<T>::type v) { bool is_null (false); // Can't be NULL. value_traits<T, id_boolean>::set_image (image_, is_null, v); @@ -1218,7 +1382,7 @@ namespace odb template <typename T> struct query_param_impl<T, id_smallint>: query_param { - query_param_impl (ref_bind<T> r) : query_param (&r.ref) {} + query_param_impl (ref_bind<T> r) : query_param (r.ptr ()) {} query_param_impl (val_bind<T> v) : query_param (0) {init (v.val);} virtual bool @@ -1243,7 +1407,7 @@ namespace odb private: void - init (const T& v) + init (typename decay_traits<T>::type v) { bool is_null (false); // Can't be NULL. value_traits<T, id_smallint>::set_image (image_, is_null, v); @@ -1258,7 +1422,7 @@ namespace odb template <typename T> struct query_param_impl<T, id_integer>: query_param { - query_param_impl (ref_bind<T> r) : query_param (&r.ref) {} + query_param_impl (ref_bind<T> r) : query_param (r.ptr ()) {} query_param_impl (val_bind<T> v) : query_param (0) {init (v.val);} virtual bool @@ -1283,7 +1447,7 @@ namespace odb private: void - init (const T& v) + init (typename decay_traits<T>::type v) { bool is_null (false); // Can't be NULL. value_traits<T, id_integer>::set_image (image_, is_null, v); @@ -1298,7 +1462,7 @@ namespace odb template <typename T> struct query_param_impl<T, id_bigint>: query_param { - query_param_impl (ref_bind<T> r) : query_param (&r.ref) {} + query_param_impl (ref_bind<T> r) : query_param (r.ptr ()) {} query_param_impl (val_bind<T> v) : query_param (0) {init (v.val);} virtual bool @@ -1323,7 +1487,7 @@ namespace odb private: void - init (const T& v) + init (typename decay_traits<T>::type v) { bool is_null (false); // Can't be NULL. value_traits<T, id_bigint>::set_image (image_, is_null, v); @@ -1338,7 +1502,7 @@ namespace odb template <typename T> struct query_param_impl<T, id_real>: query_param { - query_param_impl (ref_bind<T> r) : query_param (&r.ref) {} + query_param_impl (ref_bind<T> r) : query_param (r.ptr ()) {} query_param_impl (val_bind<T> v) : query_param (0) {init (v.val);} virtual bool @@ -1363,7 +1527,7 @@ namespace odb private: void - init (const T& v) + init (typename decay_traits<T>::type v) { bool is_null (false); // Can't be NULL. value_traits<T, id_real>::set_image (image_, is_null, v); @@ -1378,7 +1542,7 @@ namespace odb template <typename T> struct query_param_impl<T, id_double>: query_param { - query_param_impl (ref_bind<T> r) : query_param (&r.ref) {} + query_param_impl (ref_bind<T> r) : query_param (r.ptr ()) {} query_param_impl (val_bind<T> v) : query_param (0) {init (v.val);} virtual bool @@ -1403,7 +1567,7 @@ namespace odb private: void - init (const T& v) + init (typename decay_traits<T>::type v) { bool is_null (false); // Can't be NULL. value_traits<T, id_double>::set_image (image_, is_null, v); @@ -1418,7 +1582,7 @@ namespace odb template <typename T> struct query_param_impl<T, id_numeric>: query_param { - query_param_impl (ref_bind<T> r) : query_param (&r.ref) {} + query_param_impl (ref_bind<T> r) : query_param (r.ptr ()) {} query_param_impl (val_bind<T> v) : query_param (0) {init (v.val);} virtual bool @@ -1444,7 +1608,7 @@ namespace odb private: bool - init (const T& v) + init (typename decay_traits<T>::type v) { bool is_null (false); // Can't be NULL. std::size_t size (0), cap (buffer_.capacity ()); @@ -1463,7 +1627,7 @@ namespace odb template <typename T> struct query_param_impl<T, id_date>: query_param { - query_param_impl (ref_bind<T> r) : query_param (&r.ref) {} + query_param_impl (ref_bind<T> r) : query_param (r.ptr ()) {} query_param_impl (val_bind<T> v) : query_param (0) {init (v.val);} virtual bool @@ -1488,7 +1652,7 @@ namespace odb private: void - init (const T& v) + init (typename decay_traits<T>::type v) { bool is_null (false); // Can't be NULL. value_traits<T, id_date>::set_image (image_, is_null, v); @@ -1503,7 +1667,7 @@ namespace odb template <typename T> struct query_param_impl<T, id_time>: query_param { - query_param_impl (ref_bind<T> r) : query_param (&r.ref) {} + query_param_impl (ref_bind<T> r) : query_param (r.ptr ()) {} query_param_impl (val_bind<T> v) : query_param (0) {init (v.val);} virtual bool @@ -1528,7 +1692,7 @@ namespace odb private: void - init (const T& v) + init (typename decay_traits<T>::type v) { bool is_null (false); // Can't be NULL. value_traits<T, id_time>::set_image (image_, is_null, v); @@ -1543,7 +1707,7 @@ namespace odb template <typename T> struct query_param_impl<T, id_timestamp>: query_param { - query_param_impl (ref_bind<T> r) : query_param (&r.ref) {} + query_param_impl (ref_bind<T> r) : query_param (r.ptr ()) {} query_param_impl (val_bind<T> v) : query_param (0) {init (v.val);} virtual bool @@ -1568,7 +1732,7 @@ namespace odb private: void - init (const T& v) + init (typename decay_traits<T>::type v) { bool is_null (false); // Can't be NULL. value_traits<T, id_timestamp>::set_image (image_, is_null, v); @@ -1583,7 +1747,7 @@ namespace odb template <typename T> struct query_param_impl<T, id_string>: query_param { - query_param_impl (ref_bind<T> r) : query_param (&r.ref) {} + query_param_impl (ref_bind<T> r) : query_param (r.ptr ()) {} query_param_impl (val_bind<T> v) : query_param (0) {init (v.val);} virtual bool @@ -1609,7 +1773,7 @@ namespace odb private: bool - init (const T& v) + init (typename decay_traits<T>::type v) { bool is_null (false); // Can't be NULL. std::size_t size (0), cap (buffer_.capacity ()); @@ -1628,7 +1792,7 @@ namespace odb template <typename T> struct query_param_impl<T, id_bytea>: query_param { - query_param_impl (ref_bind<T> r) : query_param (&r.ref) {} + query_param_impl (ref_bind<T> r) : query_param (r.ptr ()) {} query_param_impl (val_bind<T> v) : query_param (0) {init (v.val);} virtual bool @@ -1654,7 +1818,7 @@ namespace odb private: bool - init (const T& v) + init (typename decay_traits<T>::type v) { bool is_null (false); // Can't be NULL. std::size_t size (0), cap (buffer_.capacity ()); @@ -1673,7 +1837,7 @@ namespace odb template <typename T> struct query_param_impl<T, id_bit>: query_param { - query_param_impl (ref_bind<T> r) : query_param (&r.ref) {} + query_param_impl (ref_bind<T> r) : query_param (r.ptr ()) {} query_param_impl (val_bind<T> v) : query_param (0) {init (v.val);} virtual bool @@ -1693,7 +1857,7 @@ namespace odb private: bool - init (const T& v) + init (typename decay_traits<T>::type v) { bool is_null (false); // Can't be NULL. std::size_t size (0), cap (buffer_.capacity ()); @@ -1717,7 +1881,7 @@ namespace odb template <typename T> struct query_param_impl<T, id_varbit>: query_param { - query_param_impl (ref_bind<T> r) : query_param (&r.ref) {} + query_param_impl (ref_bind<T> r) : query_param (r.ptr ()) {} query_param_impl (val_bind<T> v) : query_param (0) {init (v.val);} virtual bool @@ -1743,7 +1907,7 @@ namespace odb private: bool - init (const T& v) + init (typename decay_traits<T>::type v) { bool is_null (false); // Can't be NULL. std::size_t size (0), cap (buffer_.capacity ()); @@ -1762,7 +1926,7 @@ namespace odb template <typename T> struct query_param_impl<T, id_uuid>: query_param { - query_param_impl (ref_bind<T> r) : query_param (&r.ref) {} + query_param_impl (ref_bind<T> r) : query_param (r.ptr ()) {} query_param_impl (val_bind<T> v) : query_param (0) {init (v.val);} virtual bool @@ -1787,7 +1951,7 @@ namespace odb private: void - init (const T& v) + init (typename decay_traits<T>::type v) { bool is_null (false); // Can't be NULL. value_traits<T, id_uuid>::set_image (buffer_, is_null, v); diff --git a/odb/pgsql/query.txx b/odb/pgsql/query.txx index 84fd8ca..66296e9 100644 --- a/odb/pgsql/query.txx +++ b/odb/pgsql/query.txx @@ -26,7 +26,7 @@ namespace odb // template <typename T, database_type_id ID> query_base query_column<T, ID>:: - 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 <typename T, database_type_id ID> query_base query_column<T, ID>:: - 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 <typename T, database_type_id ID> query_base query_column<T, ID>:: - 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 <typename T, database_type_id ID> query_base query_column<T, ID>:: - 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/pgsql/traits.cxx b/odb/pgsql/traits.cxx index ec220ff..6f67d07 100644 --- a/odb/pgsql/traits.cxx +++ b/odb/pgsql/traits.cxx @@ -15,7 +15,6 @@ namespace odb // // default_value_traits<std::string, id_string> // - void default_value_traits<std::string, id_string>:: set_image (buffer& b, size_t& n, @@ -35,7 +34,6 @@ namespace odb // // c_string_value_traits // - void c_string_value_traits:: set_image (buffer& b, size_t& n, @@ -53,9 +51,53 @@ namespace odb } // - // default_value_traits<vector<char>, id_bytea> + // 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<vector<char>, id_bytea> + // void default_value_traits<vector<char>, id_bytea>:: set_image (details::buffer& b, size_t& n, @@ -77,7 +119,6 @@ namespace odb // // default_value_traits<vector<unsigned char>, id_bytea> // - void default_value_traits<vector<unsigned char>, id_bytea>:: set_image (details::buffer& b, size_t& n, diff --git a/odb/pgsql/traits.hxx b/odb/pgsql/traits.hxx index 0267527..7983571 100644 --- a/odb/pgsql/traits.hxx +++ b/odb/pgsql/traits.hxx @@ -403,7 +403,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 @@ -423,23 +423,114 @@ namespace odb }; template <> + struct LIBODB_PGSQL_EXPORT default_value_traits<char*, id_string>: + c_string_value_traits {}; + + template <> struct LIBODB_PGSQL_EXPORT default_value_traits<const char*, id_string>: - c_string_value_traits + c_string_value_traits {}; + + // char[N] specializations. + // + struct LIBODB_PGSQL_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 <std::size_t N> - struct default_value_traits<char[N], id_string>: c_string_value_traits + struct default_value_traits<char[N], id_string> { + 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<char, N> (string) specialization. + // +#ifdef ODB_CXX11 template <std::size_t N> - struct default_value_traits<const char[N], id_string>: - c_string_value_traits + struct default_value_traits<std::array<char, N>, id_string> { - typedef const char query_type[N]; + typedef std::array<char, N> value_type; + typedef std::array<char, N> 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_PGSQL_EXPORT default_value_traits<char, id_string> + { + 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); + } }; // std::vector<char> (buffer) specialization. @@ -789,6 +880,12 @@ namespace odb }; template <> + struct default_type_traits<char*> + { + static const database_type_id db_type_id = id_string; + }; + + template <> struct default_type_traits<const char*> { static const database_type_id db_type_id = id_string; @@ -800,14 +897,20 @@ namespace odb static const database_type_id db_type_id = id_string; }; - template <std::size_t N> - struct default_type_traits<const char[N]> + template <> + struct default_type_traits<char> { static const database_type_id db_type_id = id_string; }; // Binary types. // + template <std::size_t N> + struct default_type_traits<unsigned char[N]> + { + static const database_type_id db_type_id = id_bytea; + }; + template <> struct default_type_traits<std::vector<char> > { |