aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2013-01-24 15:10:21 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2013-01-24 15:10:21 +0200
commit057c8299fb1fec24338404b28f2b33473e547bc8 (patch)
treeb5b3d338fd305456b4f8681bddf2529a2272d238
parentd9984b4dd6e81ac2bb3315f41c686c06ce33e2f8 (diff)
Add support for mapping char[N] to CHAR/VARCHAR database types
Also improve query support for arrays (decaying).
-rw-r--r--odb/mssql/mssql-types.hxx3
-rw-r--r--odb/mssql/query.hxx418
-rw-r--r--odb/mssql/query.txx10
-rw-r--r--odb/mssql/traits.cxx100
-rw-r--r--odb/mssql/traits.hxx626
-rw-r--r--odb/mssql/traits.txx262
6 files changed, 1171 insertions, 248 deletions
diff --git a/odb/mssql/mssql-types.hxx b/odb/mssql/mssql-types.hxx
index 9ab7082..4166a21 100644
--- a/odb/mssql/mssql-types.hxx
+++ b/odb/mssql/mssql-types.hxx
@@ -53,8 +53,7 @@ namespace odb
chunk_type, // The position of this chunk; chunk_first means
// this is the first call, chunk_last means there
// is no more data, chunk_null means this value is
- // NULL, and chunk_one means the value is empty
- // (in this case *total_size is 0).
+ // NULL, and chunk_one means the value is empty.
std::size_t size_left, // Contains the amount of data left or 0 if this
// information is not available.
void* temp_buffer, // A temporary buffer that may be used by the
diff --git a/odb/mssql/query.hxx b/odb/mssql/query.hxx
index d9a84e4..3a82932 100644
--- a/odb/mssql/query.hxx
+++ b/odb/mssql/query.hxx
@@ -38,39 +38,96 @@ namespace odb
// 0. As a result, for scale, the not specific special value will
// be 0xFFFF (USHORT_MAX).
//
-
template <typename T>
- class val_bind
+ struct val_bind
{
- public:
+ typedef const T& type;
+
explicit
- val_bind (const T& v, unsigned short p = 0, unsigned short s = 0xFFFF)
- : val (v), prec (p), scale (s)
- {
- }
+ val_bind (type v, unsigned short p = 0, unsigned short s = 0xFFFF)
+ : val (v), prec (p), scale (s) {}
- const T& val;
+ type val;
+
+ unsigned short prec;
+ unsigned short scale;
+ };
+
+ template <typename T, std::size_t N>
+ struct val_bind<T[N]>
+ {
+ typedef const T* type;
+
+ explicit
+ val_bind (type v, unsigned short p = 0, unsigned short s = 0xFFFF)
+ : val (v), prec (p), scale (s) {}
+
+ type val;
unsigned short prec;
unsigned short scale;
};
template <typename T>
- class ref_bind
+ struct ref_bind
{
- public:
+ typedef const T& type;
+
explicit
- ref_bind (const T& r, unsigned short p = 0, unsigned short s = 0xFFFF)
- : ref (r) , prec (p), scale (s)
- {
- }
+ ref_bind (type r, unsigned short p = 0, unsigned short s = 0xFFFF)
+ : ref (r), prec (p), scale (s) {}
+
+ const void*
+ ptr () const {return &ref;}
+
+ type ref;
+
+ unsigned short prec;
+ unsigned short scale;
+ };
- const T& ref;
+ template <typename T, std::size_t N>
+ struct ref_bind<T[N]>
+ {
+ typedef const T* type;
+
+ explicit
+ ref_bind (type r, unsigned short p = 0, unsigned short s = 0xFFFF)
+ : ref (r), prec (p), scale (s) {}
+
+ // Allow implicit conversion from decayed ref_bind's.
+ //
+ ref_bind (ref_bind<T*> r): ref (r.ref), prec (r.prec), scale (r.scale) {}
+ ref_bind (ref_bind<const T*> r)
+ : ref (r.ref), prec (r.prec), scale (r.scale) {}
+
+ const void*
+ ptr () const {return ref;}
+
+ type ref;
unsigned short prec;
unsigned short scale;
};
+ template <typename T, database_type_id ID>
+ struct val_bind_typed: val_bind<T>
+ {
+ explicit
+ val_bind_typed (typename val_bind<T>::type v,
+ unsigned short p = 0,
+ unsigned short s = 0xFFFF): val_bind<T> (v, p, s) {}
+ };
+
+ template <typename T, database_type_id ID>
+ struct ref_bind_typed: ref_bind<T>
+ {
+ explicit
+ ref_bind_typed (typename ref_bind<T>::type r,
+ unsigned short p = 0,
+ unsigned short s = 0xFFFF): ref_bind<T> (r, p, s) {}
+ };
+
struct LIBODB_MSSQL_EXPORT query_param: details::shared_base
{
typedef mssql::bind bind_type;
@@ -166,8 +223,15 @@ namespace odb
query_base (val_bind<T> v)
: binding_ (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)
+ {
+ *this += v;
}
template <typename T>
@@ -175,8 +239,15 @@ namespace odb
query_base (ref_bind<T> r)
: binding_ (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)
+ {
+ *this += r;
}
template <database_type_id ID>
@@ -237,6 +308,13 @@ namespace odb
return val_bind<T> (x, prec, scale);
}
+ template <database_type_id ID, typename T>
+ static val_bind_typed<T, ID>
+ _val (const T& x, unsigned short prec = 0, unsigned short scale = 0xFFFF)
+ {
+ return val_bind_typed<T, ID> (x, prec, scale);
+ }
+
template <typename T>
static ref_bind<T>
_ref (const T& x, unsigned short prec = 0, unsigned short scale = 0xFFFF)
@@ -244,6 +322,13 @@ namespace odb
return ref_bind<T> (x, prec, scale);
}
+ template <database_type_id ID, typename T>
+ static ref_bind_typed<T, ID>
+ _ref (const T& x, unsigned short prec = 0, unsigned short scale = 0xFFFF)
+ {
+ return ref_bind_typed<T, ID> (x, prec, scale);
+ }
+
public:
query_base&
operator+= (const query_base&);
@@ -264,6 +349,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)
@@ -273,6 +369,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:
@@ -334,16 +441,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;
@@ -353,6 +470,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;
@@ -361,6 +487,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)
{
@@ -388,16 +533,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;
@@ -407,6 +562,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;
@@ -415,6 +579,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_MSSQL_EXPORT query_base
operator&& (const query_base& x, const query_base& y);
@@ -482,23 +665,11 @@ namespace odb
unsigned short scale_;
};
- 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 shalow copies of the table, column, and conversion
// expression. The latter can be NULL.
//
@@ -541,16 +712,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
@@ -560,7 +732,7 @@ namespace odb
//
public:
query_base
- equal (const T& v) const
+ equal (decayed_type v) const
{
return equal (val_bind<T> (v));
}
@@ -581,8 +753,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
@@ -598,13 +769,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);
}
@@ -651,7 +822,7 @@ namespace odb
//
public:
query_base
- unequal (const T& v) const
+ unequal (decayed_type v) const
{
return unequal (val_bind<T> (v));
}
@@ -672,8 +843,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
@@ -689,13 +859,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);
}
@@ -742,7 +912,7 @@ namespace odb
//
public:
query_base
- less (const T& v) const
+ less (decayed_type v) const
{
return less (val_bind<T> (v));
}
@@ -763,8 +933,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
@@ -780,13 +949,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);
}
@@ -833,7 +1002,7 @@ namespace odb
//
public:
query_base
- greater (const T& v) const
+ greater (decayed_type v) const
{
return greater (val_bind<T> (v));
}
@@ -854,8 +1023,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
@@ -871,13 +1039,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);
}
@@ -924,7 +1092,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));
}
@@ -945,8 +1113,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
@@ -962,13 +1129,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);
}
@@ -1015,7 +1182,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));
}
@@ -1036,8 +1203,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
@@ -1053,13 +1219,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);
}
@@ -1111,7 +1277,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 += "=";
@@ -1125,7 +1292,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 += "!=";
@@ -1139,7 +1307,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 += "<";
@@ -1153,7 +1322,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 += ">";
@@ -1167,7 +1337,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 += "<=";
@@ -1181,7 +1352,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 += ">=";
@@ -1239,7 +1411,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
@@ -1259,7 +1431,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_bit>::set_image (image_, is_null, v);
@@ -1276,7 +1448,7 @@ namespace odb
template <typename T>
struct query_param_impl<T, id_tinyint>: 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
@@ -1296,7 +1468,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_tinyint>::set_image (image_, is_null, v);
@@ -1313,7 +1485,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
@@ -1333,7 +1505,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);
@@ -1350,7 +1522,7 @@ namespace odb
template <typename T>
struct query_param_impl<T, id_int>: 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
@@ -1370,7 +1542,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_int>::set_image (image_, is_null, v);
@@ -1387,7 +1559,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
@@ -1407,7 +1579,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);
@@ -1425,7 +1597,7 @@ namespace odb
struct query_param_impl<T, id_decimal>: query_param
{
query_param_impl (ref_bind<T> r)
- : query_param (&r.ref),
+ : query_param (r.ptr ()),
prec_ (r.prec != 0 ? r.prec : 18), // Default is 18.
scale_ (r.scale != 0xFFFF ? r.scale : 0) // Default is 0.
{
@@ -1459,7 +1631,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_decimal>::set_image (image_, is_null, v);
@@ -1479,7 +1651,7 @@ namespace odb
template <typename T>
struct query_param_impl<T, id_smallmoney>: 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
@@ -1499,7 +1671,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_smallmoney>::set_image (image_, is_null, v);
@@ -1516,7 +1688,7 @@ namespace odb
template <typename T>
struct query_param_impl<T, id_money>: 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
@@ -1536,7 +1708,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_money>::set_image (image_, is_null, v);
@@ -1554,7 +1726,7 @@ namespace odb
struct query_param_impl<T, id_float4>: query_param
{
query_param_impl (ref_bind<T> r)
- : query_param (&r.ref),
+ : query_param (r.ptr ()),
prec_ (r.prec != 0 ? r.prec : 24)
{
}
@@ -1584,7 +1756,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_float4>::set_image (image_, is_null, v);
@@ -1603,7 +1775,7 @@ namespace odb
struct query_param_impl<T, id_float8>: query_param
{
query_param_impl (ref_bind<T> r)
- : query_param (&r.ref),
+ : query_param (r.ptr ()),
prec_ (r.prec != 0 ? r.prec : 53)
{
}
@@ -1633,7 +1805,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_float8>::set_image (image_, is_null, v);
@@ -1652,7 +1824,7 @@ namespace odb
struct query_param_impl<T, id_string>: query_param
{
query_param_impl (ref_bind<T> r)
- : query_param (&r.ref),
+ : query_param (r.ptr ()),
// Default to short data max (1024).
buf_ (r.prec != 0 ? r.prec : 1024)
{
@@ -1686,7 +1858,7 @@ namespace odb
private:
void
- init (const T& v)
+ init (typename decay_traits<T>::type v)
{
bool is_null (false); // Can't be NULL.
std::size_t size (0);
@@ -1706,7 +1878,7 @@ namespace odb
struct query_param_impl<T, id_nstring>: query_param
{
query_param_impl (ref_bind<T> r)
- : query_param (&r.ref),
+ : query_param (r.ptr ()),
// Precision is in 2-byte chars. Default to short data max (1024).
buf_ (r.prec != 0 ? r.prec * 2 : 1024)
{
@@ -1740,7 +1912,7 @@ namespace odb
private:
void
- init (const T& v)
+ init (typename decay_traits<T>::type v)
{
bool is_null (false); // Can't be NULL.
std::size_t size (0);
@@ -1764,7 +1936,7 @@ namespace odb
struct query_param_impl<T, id_binary>: query_param
{
query_param_impl (ref_bind<T> r)
- : query_param (&r.ref),
+ : query_param (r.ptr ()),
// Default to short data max (1024).
buf_ (r.prec != 0 ? r.prec : 1024)
{
@@ -1796,7 +1968,7 @@ namespace odb
private:
void
- init (const T& v)
+ init (typename decay_traits<T>::type v)
{
bool is_null (false); // Can't be NULL.
std::size_t size (0);
@@ -1838,7 +2010,7 @@ namespace odb
long_query_param_impl
{
query_param_impl (ref_bind<T> r)
- : query_param (&r.ref), prec_ (r.prec)
+ : query_param (r.ptr ()), prec_ (r.prec)
{
}
@@ -1889,7 +2061,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_long_string>::set_image (
@@ -1911,7 +2083,7 @@ namespace odb
long_query_param_impl
{
query_param_impl (ref_bind<T> r)
- : query_param (&r.ref), prec_ (r.prec)
+ : query_param (r.ptr ()), prec_ (r.prec)
{
}
@@ -1962,7 +2134,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_long_nstring>::set_image (
@@ -1984,7 +2156,7 @@ namespace odb
long_query_param_impl
{
query_param_impl (ref_bind<T> r)
- : query_param (&r.ref), prec_ (r.prec)
+ : query_param (r.ptr ()), prec_ (r.prec)
{
}
@@ -2033,7 +2205,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_long_binary>::set_image (
@@ -2053,7 +2225,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
@@ -2073,7 +2245,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);
@@ -2091,7 +2263,7 @@ namespace odb
struct query_param_impl<T, id_time>: query_param
{
query_param_impl (ref_bind<T> r)
- : query_param (&r.ref),
+ : query_param (r.ptr ()),
scale_ (r.scale != 0xFFFF ? r.scale : 7) // Default is 7.
{
}
@@ -2121,7 +2293,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_, scale_, is_null, v);
@@ -2140,7 +2312,7 @@ namespace odb
struct query_param_impl<T, id_datetime>: query_param
{
query_param_impl (ref_bind<T> r)
- : query_param (&r.ref),
+ : query_param (r.ptr ()),
scale_ (r.scale != 0xFFFF ? r.scale : 7) // Default to datetime2/7.
{
}
@@ -2170,7 +2342,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_datetime>::set_image (image_, scale_, is_null, v);
@@ -2189,7 +2361,7 @@ namespace odb
struct query_param_impl<T, id_datetimeoffset>: query_param
{
query_param_impl (ref_bind<T> r)
- : query_param (&r.ref),
+ : query_param (r.ptr ()),
scale_ (r.scale != 0xFFFF ? r.scale : 7) // Default is 7.
{
}
@@ -2219,7 +2391,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_datetimeoffset>::set_image (
@@ -2238,7 +2410,7 @@ namespace odb
template <typename T>
struct query_param_impl<T, id_uniqueidentifier>: 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
@@ -2258,7 +2430,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_uniqueidentifier>::set_image (image_, is_null, v);
@@ -2275,7 +2447,7 @@ namespace odb
template <typename T>
struct query_param_impl<T, id_rowversion>: 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
@@ -2295,7 +2467,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_rowversion>::set_image (image_, is_null, v);
diff --git a/odb/mssql/query.txx b/odb/mssql/query.txx
index d77ea83..fffbf87 100644
--- a/odb/mssql/query.txx
+++ b/odb/mssql/query.txx
@@ -27,7 +27,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 (";
@@ -40,7 +40,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 (";
@@ -55,7 +55,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 (";
@@ -72,7 +73,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/mssql/traits.cxx b/odb/mssql/traits.cxx
index 906473f..aba0433 100644
--- a/odb/mssql/traits.cxx
+++ b/odb/mssql/traits.cxx
@@ -13,9 +13,54 @@ namespace odb
namespace mssql
{
//
- // default_value_traits<std::string, id_long_string>
+ // c_array_value_traits_base
//
+ void c_array_value_traits_base::
+ set_value (char* const& v,
+ const char* b,
+ size_t n,
+ bool is_null,
+ size_t N)
+ {
+ if (!is_null)
+ {
+ n = n < N ? n : N;
+
+ if (n != 0)
+ memcpy (v, b, n);
+ }
+ else
+ n = 0;
+ if (n != N) // Append '\0' if there is space.
+ v[n] = '\0';
+ }
+
+ void c_array_value_traits_base::
+ set_image (char* b,
+ size_t c,
+ 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 > c)
+ n = c;
+
+ if (n != 0)
+ memcpy (b, v, n);
+ }
+
+ //
+ // default_value_traits<std::string, id_long_string>
+ //
void default_value_traits<string, id_long_string>::
param_callback (const void* context,
size_t*,
@@ -141,7 +186,6 @@ namespace odb
//
// c_long_string_value_traits
//
-
void c_string_long_value_traits::
param_callback (const void* context,
size_t*,
@@ -157,9 +201,54 @@ namespace odb
}
//
- // wstring_long_value_traits<2>
+ // c_warray_value_traits_base
//
+ void c_warray_value_traits_base::
+ set_value (wchar_t* const& v,
+ const ucs2_char* b,
+ size_t n,
+ bool is_null,
+ size_t N)
+ {
+ if (!is_null)
+ {
+ n = n < N ? n : N;
+
+ if (n != 0)
+ functions::assign (v, b, n);
+ }
+ else
+ n = 0;
+
+ if (n != N) // Append '\0' if there is space.
+ v[n] = L'\0';
+ }
+
+ void c_warray_value_traits_base::
+ set_image (ucs2_char* b,
+ size_t c,
+ 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);
+
+ if (n > c)
+ n = c;
+ if (n != 0)
+ functions::assign (b, v, n);
+ }
+
+ //
+ // wstring_long_value_traits<2>
+ //
void wstring_long_value_traits<2>::
param_callback (const void* context,
size_t*,
@@ -234,7 +323,6 @@ namespace odb
//
// wstring_long_value_traits<4>
//
-
#ifndef _WIN32
void wstring_long_value_traits<4>::
param_callback (const void* context,
@@ -332,7 +420,6 @@ namespace odb
//
// c_wstring_long_value_traits<2>
//
-
void c_wstring_long_value_traits<2>::
param_callback (const void* context,
size_t*,
@@ -350,7 +437,6 @@ namespace odb
//
// c_wstring_long_value_traits<4>
//
-
#ifndef _WIN32
void c_wstring_long_value_traits<4>::
param_callback (const void* context,
@@ -397,7 +483,6 @@ namespace odb
//
// default_value_traits<std::vector<char>, id_long_binary>
//
-
void default_value_traits<std::vector<char>, id_long_binary>::
param_callback (const void* context,
size_t*,
@@ -466,7 +551,6 @@ namespace odb
//
// default_value_traits<std::vector<unsigned char>, id_long_binary>
//
-
void default_value_traits<std::vector<unsigned char>, id_long_binary>::
param_callback (const void* context,
size_t*,
diff --git a/odb/mssql/traits.hxx b/odb/mssql/traits.hxx
index a74b002..207a30a 100644
--- a/odb/mssql/traits.hxx
+++ b/odb/mssql/traits.hxx
@@ -602,7 +602,7 @@ namespace odb
}
};
- // const char* specialization for string.
+ // char*/const char* specialization for string.
//
// Specialization for const char* which only supports initialization
// of an image from the value but not the other way around. This way
@@ -633,23 +633,118 @@ namespace odb
};
template <>
+ struct LIBODB_MSSQL_EXPORT default_value_traits<char*, id_string>:
+ c_string_value_traits {};
+
+ template <>
struct LIBODB_MSSQL_EXPORT default_value_traits<const char*, id_string>:
- c_string_value_traits
+ c_string_value_traits {};
+
+ // char[N] specialization.
+ //
+ struct LIBODB_MSSQL_EXPORT c_array_value_traits_base
{
- typedef const char* query_type;
+ static void
+ set_value (char* const& v,
+ const char* b,
+ std::size_t n,
+ bool is_null,
+ std::size_t N);
+
+ static void
+ set_image (char* b,
+ std::size_t c,
+ 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 char* 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 (char* b,
+ std::size_t c,
+ std::size_t& n,
+ bool& is_null,
+ const char* v)
+ {
+ c_array_value_traits_base::set_image (b, c, 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 char* 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 (char* b,
+ std::size_t c,
+ std::size_t& n,
+ bool& is_null,
+ const value_type& v)
+ {
+ c_array_value_traits_base::set_image (b, c, n, is_null, v.data (), N);
+ }
+ };
+#endif
+
+ // char specialization.
+ //
+ template <>
+ struct LIBODB_MSSQL_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 char* 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 (char* b,
+ std::size_t c,
+ std::size_t& n,
+ bool& is_null,
+ char v)
+ {
+ c_array_value_traits_base::set_image (b, c, n, is_null, &v, 1);
+ }
};
// std::string specialization for long_string.
@@ -702,7 +797,7 @@ namespace odb
std::size_t tmp_capacity);
};
- // const char* specialization for long_string.
+ // char*/const char* specialization for long_string.
//
class LIBODB_MSSQL_EXPORT c_string_long_value_traits
{
@@ -732,26 +827,112 @@ namespace odb
};
template <>
- struct LIBODB_MSSQL_EXPORT default_value_traits<const char*,
- id_long_string>:
- c_string_long_value_traits
+ struct LIBODB_MSSQL_EXPORT default_value_traits<
+ char*, id_long_string>: c_string_long_value_traits {};
+
+ template <>
+ struct LIBODB_MSSQL_EXPORT default_value_traits<
+ const char*, id_long_string>: c_string_long_value_traits {};
+
+ // char[N] specialization for long_string.
+ //
+ template <std::size_t N>
+ struct c_array_long_value_traits_base
{
- typedef const char* query_type;
+ static void
+ set_value (char* const& v,
+ result_callback_type& cb,
+ void*& context)
+ {
+ cb = &result_callback;
+ context = v;
+ }
+
+ static void
+ set_image (param_callback_type& cb,
+ const void*& context,
+ bool& is_null,
+ const char* v)
+ {
+ is_null = false;
+ cb = &param_callback;
+ context = v;
+ }
+
+ static void
+ param_callback (const void* context,
+ std::size_t* position,
+ const void** buffer,
+ std::size_t* size,
+ chunk_type* chunk,
+ void* tmp_buffer,
+ std::size_t tmp_capacity);
+
+ static void
+ result_callback (void* context,
+ std::size_t* position,
+ void** buffer,
+ std::size_t* size,
+ chunk_type chunk,
+ std::size_t size_left,
+ void* tmp_buffer,
+ std::size_t tmp_capacity);
};
template <std::size_t N>
- struct default_value_traits<char[N], id_long_string>:
- c_string_long_value_traits
+ struct default_value_traits<char[N], id_long_string>
{
+ typedef char* value_type;
typedef char query_type[N];
+ typedef long_callback image_type;
+
+ static void
+ set_value (char* const& v,
+ result_callback_type& cb,
+ void*& context)
+ {
+ c_array_long_value_traits_base<N>::set_value (v, cb, context);
+ }
+
+ static void
+ set_image (param_callback_type& cb,
+ const void*& context,
+ bool& is_null,
+ const char* v)
+ {
+ c_array_long_value_traits_base<N>::set_image (cb, context, is_null, v);
+ }
};
+ // std::array<char, N> (long_string) specialization.
+ //
+#ifdef ODB_CXX11
template <std::size_t N>
- struct default_value_traits<const char[N], id_long_string>:
- c_string_long_value_traits
+ struct default_value_traits<std::array<char, N>, id_long_string>
{
- typedef const char query_type[N];
+ typedef std::array<char, N> value_type;
+ typedef std::array<char, N> query_type;
+ typedef long_callback image_type;
+
+ static void
+ set_value (value_type& v,
+ result_callback_type& cb,
+ void*& context)
+ {
+ c_array_long_value_traits_base<N>::set_value (v.data (), cb, context);
+ }
+
+ static void
+ set_image (param_callback_type& cb,
+ const void*& context,
+ bool& is_null,
+ const value_type& v)
+ {
+ c_array_long_value_traits_base<N>::set_image (
+ cb, context, is_null, v.data ());
+ }
};
+#endif
// std::wstring specialization for nstring.
//
@@ -770,6 +951,13 @@ namespace odb
for (std::size_t i (0); i < n; ++i)
b[i] = static_cast<ucs2_char> (s[i]);
}
+
+ static void
+ assign (wchar_t* s, const ucs2_char* b, std::size_t n)
+ {
+ for (std::size_t i (0); i < n; ++i)
+ s[i] = static_cast<wchar_t> (b[i]);
+ }
};
template <>
@@ -784,9 +972,19 @@ namespace odb
static void
assign (ucs2_char* b, const wchar_t* s, std::size_t n)
{
- if (n != 0)
- std::memcpy (b, s, n * sizeof (ucs2_char));
+ std::memcpy (b, s, n * sizeof (ucs2_char));
}
+
+ // On Windows ucs2_char is wchar_t which makes this function
+ // the same as the one above.
+ //
+#ifndef _WIN32
+ static void
+ assign (wchar_t* s, const ucs2_char* b, std::size_t n)
+ {
+ std::memcpy (s, b, n * sizeof (ucs2_char));
+ }
+#endif
};
template <>
@@ -823,11 +1021,12 @@ namespace odb
if (n > c)
n = c;
- functions::assign (b, v.c_str (), n);
+ if (n != 0)
+ functions::assign (b, v.c_str (), n);
}
};
- // const wchar_t* specialization for nstring.
+ // wchar_t*/const wchar_t* specialization for nstring.
//
class LIBODB_MSSQL_EXPORT c_wstring_value_traits
{
@@ -850,30 +1049,126 @@ namespace odb
if (n > c)
n = c;
- functions::assign (b, v, n);
+ if (n != 0)
+ functions::assign (b, v, n);
}
};
template <>
- struct LIBODB_MSSQL_EXPORT default_value_traits<const wchar_t*,
- id_nstring>:
- c_wstring_value_traits
+ struct LIBODB_MSSQL_EXPORT default_value_traits<wchar_t*, id_nstring>:
+ c_wstring_value_traits {};
+
+ template <>
+ struct LIBODB_MSSQL_EXPORT default_value_traits<
+ const wchar_t*, id_nstring>: c_wstring_value_traits {};
+
+ // wchar_t[N] specialization.
+ //
+ struct LIBODB_MSSQL_EXPORT c_warray_value_traits_base
{
- typedef const wchar_t* query_type;
+ typedef wstring_functions<> functions;
+
+ static void
+ set_value (wchar_t* const& v,
+ const ucs2_char* b,
+ std::size_t n,
+ bool is_null,
+ std::size_t N);
+
+ static void
+ set_image (ucs2_char* b,
+ std::size_t c,
+ std::size_t& n,
+ bool& is_null,
+ const wchar_t* v,
+ std::size_t N);
};
template <std::size_t N>
- struct default_value_traits<wchar_t[N], id_nstring>:
- c_wstring_value_traits
+ struct default_value_traits<wchar_t[N], id_nstring>
{
+ 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 ucs2_char* 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 (ucs2_char* b,
+ std::size_t c,
+ std::size_t& n,
+ bool& is_null,
+ const wchar_t* v)
+ {
+ c_warray_value_traits_base::set_image (b, c, n, is_null, v, N);
+ }
};
+ // std::array<wchar_t, N> (string) specialization.
+ //
+#ifdef ODB_CXX11
template <std::size_t N>
- struct default_value_traits<const wchar_t[N], id_nstring>:
- c_wstring_value_traits
+ struct default_value_traits<std::array<wchar_t, N>, id_nstring>
+ {
+ typedef std::array<wchar_t, N> value_type;
+ typedef std::array<wchar_t, N> query_type;
+ typedef details::buffer image_type;
+
+ static void
+ set_value (value_type& v,
+ const ucs2_char* 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 (ucs2_char* b,
+ std::size_t c,
+ std::size_t& n,
+ bool& is_null,
+ const value_type& v)
+ {
+ c_warray_value_traits_base::set_image (b, c, n, is_null, v.data (), N);
+ }
+ };
+#endif
+
+ // wchar_t specialization.
+ //
+ template <>
+ struct LIBODB_MSSQL_EXPORT default_value_traits<wchar_t, id_nstring>
{
- 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 ucs2_char* 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 (ucs2_char* b,
+ std::size_t c,
+ std::size_t& n,
+ bool& is_null,
+ wchar_t v)
+ {
+ c_warray_value_traits_base::set_image (b, c, n, is_null, &v, 1);
+ }
};
// std::wstring specialization for long_nstring.
@@ -958,7 +1253,7 @@ namespace odb
}
};
- // const wchar_t* specialization for long_nstring.
+ // wchar_t*/const wchar_t* specialization for long_nstring.
//
template <std::size_t = sizeof (wchar_t)>
struct c_wstring_long_value_traits;
@@ -1020,26 +1315,162 @@ namespace odb
#endif
template <>
- struct LIBODB_MSSQL_EXPORT default_value_traits<const wchar_t*,
- id_long_nstring>:
- c_wstring_long_value_traits<>
+ struct LIBODB_MSSQL_EXPORT default_value_traits<
+ wchar_t*, id_long_nstring>: c_wstring_long_value_traits<> {};
+
+ template <>
+ struct LIBODB_MSSQL_EXPORT default_value_traits<
+ const wchar_t*, id_long_nstring>: c_wstring_long_value_traits<> {};
+
+ // char[N] specialization for long_nstring.
+ //
+ template <std::size_t N, std::size_t = sizeof (wchar_t)>
+ struct c_warray_long_value_traits_base;
+
+ template <std::size_t N>
+ struct c_warray_long_value_traits_base<N, 2>
{
- typedef const wchar_t* query_type;
+ static void
+ set_value (wchar_t* const& v,
+ result_callback_type& cb,
+ void*& context)
+ {
+ cb = &result_callback;
+ context = v;
+ }
+
+ static void
+ set_image (param_callback_type& cb,
+ const void*& context,
+ bool& is_null,
+ const wchar_t* v)
+ {
+ is_null = false;
+ cb = &param_callback;
+ context = v;
+ }
+
+ static void
+ param_callback (const void* context,
+ std::size_t* position,
+ const void** buffer,
+ std::size_t* size,
+ chunk_type* chunk,
+ void* tmp_buffer,
+ std::size_t tmp_capacity);
+
+ static void
+ result_callback (void* context,
+ std::size_t* position,
+ void** buffer,
+ std::size_t* size,
+ chunk_type chunk,
+ std::size_t size_left,
+ void* tmp_buffer,
+ std::size_t tmp_capacity);
};
+#ifndef _WIN32
template <std::size_t N>
- struct default_value_traits<wchar_t[N], id_long_nstring>:
- c_wstring_long_value_traits<>
+ struct c_warray_long_value_traits_base<N, 4>
{
+ static void
+ set_value (wchar_t* const& v,
+ result_callback_type& cb,
+ void*& context)
+ {
+ cb = &result_callback;
+ context = v;
+ }
+
+ static void
+ set_image (param_callback_type& cb,
+ const void*& context,
+ bool& is_null,
+ const wchar_t* v)
+ {
+ is_null = false;
+ cb = &param_callback;
+ context = v;
+ }
+
+ static void
+ param_callback (const void* context,
+ std::size_t* position,
+ const void** buffer,
+ std::size_t* size,
+ chunk_type* chunk,
+ void* tmp_buffer,
+ std::size_t tmp_capacity);
+
+ static void
+ result_callback (void* context,
+ std::size_t* position,
+ void** buffer,
+ std::size_t* size,
+ chunk_type chunk,
+ std::size_t size_left,
+ void* tmp_buffer,
+ std::size_t tmp_capacity);
+ };
+#endif
+
+ template <std::size_t N>
+ struct default_value_traits<wchar_t[N], id_long_nstring>
+ {
+ typedef wchar_t* value_type;
typedef wchar_t query_type[N];
+ typedef long_callback image_type;
+
+ static void
+ set_value (wchar_t* const& v,
+ result_callback_type& cb,
+ void*& context)
+ {
+ c_warray_long_value_traits_base<N>::set_value (v, cb, context);
+ }
+
+ static void
+ set_image (param_callback_type& cb,
+ const void*& context,
+ bool& is_null,
+ const wchar_t* v)
+ {
+ c_warray_long_value_traits_base<N>::set_image (
+ cb, context, is_null, v);
+ }
};
+ // std::array<wchar_t, N> (long_nstring) specialization.
+ //
+#ifdef ODB_CXX11
template <std::size_t N>
- struct default_value_traits<const wchar_t[N], id_long_nstring>:
- c_wstring_long_value_traits<>
+ struct default_value_traits<std::array<wchar_t, N>, id_long_nstring>
{
- typedef const wchar_t query_type[N];
+ typedef std::array<wchar_t, N> value_type;
+ typedef std::array<wchar_t, N> query_type;
+ typedef long_callback image_type;
+
+ static void
+ set_value (value_type& v,
+ result_callback_type& cb,
+ void*& context)
+ {
+ c_warray_long_value_traits_base<N>::set_value (
+ v.data (), cb, context);
+ }
+
+ static void
+ set_image (param_callback_type& cb,
+ const void*& context,
+ bool& is_null,
+ const value_type& v)
+ {
+ c_warray_long_value_traits_base<N>::set_image (
+ cb, context, is_null, v.data ());
+ }
};
+#endif
// std::vector (buffer) specialization for binary.
//
@@ -1289,10 +1720,6 @@ namespace odb
template <typename C, std::size_t N>
struct c_array_long_binary_value_traits
{
- typedef C* value_type;
- typedef C query_type[N];
- typedef long_callback image_type;
-
static void
set_value (C* const& v,
result_callback_type& cb,
@@ -1337,21 +1764,27 @@ namespace odb
struct default_value_traits<char[N], id_long_binary>:
c_array_long_binary_value_traits<char, N>
{
+ typedef char* value_type;
+ typedef char query_type[N];
+ typedef long_callback image_type;
};
template <std::size_t N>
struct default_value_traits<unsigned char[N], id_long_binary>:
c_array_long_binary_value_traits<unsigned char, N>
{
+ typedef unsigned char* value_type;
+ typedef unsigned char query_type[N];
+ typedef long_callback image_type;
};
#ifdef ODB_CXX11
// std::array (buffer) specialization for long_binary.
//
- template <typename C, std::size_t N>
- struct array_long_binary_value_traits
+ template <std::size_t N>
+ struct default_value_traits<std::array<char, N>, id_long_binary>
{
- typedef std::array<C, N> value_type;
+ typedef std::array<char, N> value_type;
typedef value_type query_type;
typedef long_callback image_type;
@@ -1360,8 +1793,8 @@ namespace odb
result_callback_type& cb,
void*& context)
{
- cb = &result_callback;
- context = v.data ();
+ c_array_long_binary_value_traits<char, N>::set_value (
+ v.data (), cb, context);
}
static void
@@ -1370,41 +1803,36 @@ namespace odb
bool& is_null,
const value_type& v)
{
- is_null = false;
- cb = &param_callback;
- context = v.data ();
+ c_array_long_binary_value_traits<char, N>::set_image (
+ cb, context, is_null, v.data ());
}
-
- static void
- param_callback (const void* context,
- std::size_t* position,
- const void** buffer,
- std::size_t* size,
- chunk_type* chunk,
- void* tmp_buffer,
- std::size_t tmp_capacity);
-
- static void
- result_callback (void* context,
- std::size_t* position,
- void** buffer,
- std::size_t* size,
- chunk_type chunk,
- std::size_t size_left,
- void* tmp_buffer,
- std::size_t tmp_capacity);
};
template <std::size_t N>
- struct default_value_traits<std::array<char, N>, id_long_binary>:
- array_long_binary_value_traits<char, N>
+ struct default_value_traits<std::array<unsigned char, N>, id_long_binary>
{
- };
+ typedef std::array<unsigned char, N> value_type;
+ typedef value_type query_type;
+ typedef long_callback image_type;
- template <std::size_t N>
- struct default_value_traits<std::array<unsigned char, N>, id_long_binary>:
- array_long_binary_value_traits<unsigned char, N>
- {
+ static void
+ set_value (value_type& v,
+ result_callback_type& cb,
+ void*& context)
+ {
+ c_array_long_binary_value_traits<unsigned char, N>::set_value (
+ v.data (), cb, context);
+ }
+
+ static void
+ set_image (param_callback_type& cb,
+ const void*& context,
+ bool& is_null,
+ const value_type& v)
+ {
+ c_array_long_binary_value_traits<unsigned char, N>::set_image (
+ cb, context, is_null, v.data ());
+ }
};
#endif
@@ -1616,6 +2044,12 @@ namespace odb
};
template <>
+ struct default_type_traits<char*>
+ {
+ static const database_type_id db_type_id = id_long_string;
+ };
+
+ template <>
struct default_type_traits<const char*>
{
static const database_type_id db_type_id = id_long_string;
@@ -1624,13 +2058,16 @@ namespace odb
template <std::size_t N>
struct default_type_traits<char[N]>
{
- static const database_type_id db_type_id = id_long_string;
+ // Use short string by default to minimize code bloat. Can
+ // always be overridden with _val()/_ref().
+ //
+ 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_long_string;
+ static const database_type_id db_type_id = id_string;
};
// Wide string types.
@@ -1642,6 +2079,12 @@ namespace odb
};
template <>
+ struct default_type_traits<wchar_t*>
+ {
+ static const database_type_id db_type_id = id_long_nstring;
+ };
+
+ template <>
struct default_type_traits<const wchar_t*>
{
static const database_type_id db_type_id = id_long_nstring;
@@ -1650,17 +2093,26 @@ namespace odb
template <std::size_t N>
struct default_type_traits<wchar_t[N]>
{
- static const database_type_id db_type_id = id_long_nstring;
+ // Use short string by default to minimize code bloat. Can
+ // always be overridden with _val()/_ref().
+ //
+ static const database_type_id db_type_id = id_nstring;
};
- template <std::size_t N>
- struct default_type_traits<const wchar_t[N]>
+ template <>
+ struct default_type_traits<wchar_t>
{
- static const database_type_id db_type_id = id_long_nstring;
+ static const database_type_id db_type_id = id_nstring;
};
// Binary types.
//
+ template <std::size_t N>
+ struct default_type_traits<unsigned char[N]>
+ {
+ static const database_type_id db_type_id = id_long_binary;
+ };
+
template <>
struct default_type_traits<std::vector<char> >
{
diff --git a/odb/mssql/traits.txx b/odb/mssql/traits.txx
index 634097e..1e2db27 100644
--- a/odb/mssql/traits.txx
+++ b/odb/mssql/traits.txx
@@ -11,7 +11,6 @@ namespace odb
//
// wrapped_value_traits<W, ID, true>
//
-
template <typename W, database_type_id ID>
void wrapped_value_traits<W, ID, true>::
result_callback (void* context,
@@ -52,11 +51,10 @@ namespace odb
}
//
- // c_array_long_binary_value_traits
+ // c_array_long_value_traits_base
//
-
- template <typename C, std::size_t N>
- void c_array_long_binary_value_traits<C, N>::
+ template <std::size_t N>
+ void c_array_long_value_traits_base<N>::
param_callback (const void* context,
std::size_t*,
const void** buffer,
@@ -65,64 +63,281 @@ namespace odb
void*,
std::size_t)
{
+ // Figure out the length. We cannot use strlen since it may
+ // not be 0-terminated (strnlen is not standard).
+ //
+ size_t n (0);
+ for (; n != N && static_cast<const char*> (context)[n] != '\0'; ++n);
+
*buffer = context;
- *size = N;
+ *size = n;
*chunk = chunk_one;
}
- template <typename C, std::size_t N>
- void c_array_long_binary_value_traits<C, N>::
+ template <std::size_t N>
+ void c_array_long_value_traits_base<N>::
result_callback (void* context,
- std::size_t*,
+ std::size_t* position,
void** buffer,
std::size_t* size,
chunk_type chunk,
- std::size_t size_left,
+ std::size_t,
void* tmp_buf,
std::size_t tmp_capacity)
{
- // The code is similar to the vector<char> specialization.
- //
+ char* p (static_cast<char*> (context));
+
switch (chunk)
{
case chunk_null:
case chunk_one:
{
- std::memset (context, 0, N);
+ *p = '\0';
break;
}
case chunk_first:
{
- assert (size_left != 0);
+ *buffer = p;
+ *size = N;
+ break;
+ }
+ case chunk_next:
+ {
+ // ODBC insists on appending '\0' to each chunk it returns.
+ // As a result, we can get here if the last character did not
+ // fit into our buffer. There could also be more data but since
+ // there is no way to stop until we read all the data, dump
+ // the remainder into the temporary buffer.
+ //
+
+ // Use position to indicate whether this is the first "next
+ // chunk".
+ //
+ if (*position == 0)
+ *position = 1;
+ else if (*position == 1)
+ {
+ p[N - 1] = *static_cast<const char*> (tmp_buf);
+ *position = 2;
+ }
+
+ *buffer = tmp_buf;
+ *size = tmp_capacity;
+ break;
+ }
+ case chunk_last:
+ {
+ if (*position == 0)
+ {
+ if (*size < N) // Append '\0' if there is space.
+ p[*size] = '\0';
+ }
+ else if (*position == 1)
+ p[N - 1] = *static_cast<const char*> (tmp_buf);
- *buffer = context;
- *size = size_left < N ? size_left : N;
+ break;
+ }
+ }
+ }
+
+ //
+ // c_warray_long_value_traits_base<2>
+ //
+ template <std::size_t N>
+ void c_warray_long_value_traits_base<N, 2>::
+ param_callback (const void* context,
+ std::size_t*,
+ const void** buffer,
+ std::size_t* size,
+ chunk_type* chunk,
+ void*,
+ std::size_t)
+ {
+ // Figure out the length. We cannot use wcslen since it may
+ // not be 0-terminated (wcsnlen is not standard).
+ //
+ size_t n (0);
+ for (; n != N && static_cast<const wchar_t*> (context)[n] != L'\0'; ++n);
+
+ *buffer = context;
+ *size = n * 2; // In bytes.
+ *chunk = chunk_one;
+ }
+
+ template <std::size_t N>
+ void c_warray_long_value_traits_base<N, 2>::
+ result_callback (void* context,
+ std::size_t* position,
+ void** buffer,
+ std::size_t* size,
+ chunk_type chunk,
+ std::size_t,
+ void* tmp_buf,
+ std::size_t tmp_capacity)
+ {
+ wchar_t* p (static_cast<char*> (context));
+
+ switch (chunk)
+ {
+ case chunk_null:
+ case chunk_one:
+ {
+ *p = L'\0';
+ break;
+ }
+ case chunk_first:
+ {
+ *buffer = p;
+ *size = N * 2; // In bytes
break;
}
case chunk_next:
{
- // We can get here if total size is greater than N. There is
- // no way to stop until we read all the data, so dump the
- // remainder into the temporary buffer.
+ // ODBC insists on appending '\0' to each chunk it returns.
+ // As a result, we can get here if the last character did not
+ // fit into our buffer. There could also be more data but since
+ // there is no way to stop until we read all the data, dump
+ // the remainder into the temporary buffer.
//
+
+ // Use position to indicate whether this is the first "next
+ // chunk".
+ //
+ if (*position == 0)
+ *position = 1;
+ else if (*position == 1)
+ {
+ p[N - 1] = *static_cast<const wchar_t*> (tmp_buf);
+ *position = 2;
+ }
+
*buffer = tmp_buf;
*size = tmp_capacity;
break;
}
case chunk_last:
{
+ if (*position == 0)
+ {
+ size_t n (*size / 2); // In wide characters.
+ if (n < N) // Append '\0' if there is space.
+ p[n] = L'\0';
+ }
+ else if (*position == 1)
+ p[N - 1] = *static_cast<const wchar_t*> (tmp_buf);
+
break;
}
}
}
-#ifdef ODB_CXX11
+#ifndef _WIN32
//
- // array_long_binary_value_traits
+ // c_warray_long_value_traits_base<4>
//
+ template <std::size_t N>
+ void c_warray_long_value_traits_base<N, 4>::
+ param_callback (const void* context,
+ std::size_t* pos,
+ const void** buffer,
+ std::size_t* size,
+ chunk_type* chunk,
+ void* tmp_buf,
+ std::size_t tmp_capacity)
+ {
+ // Here we cannot just return the pointer to the underlying buffer
+ // since the character sizes are different. Instead we copy the
+ // data to the temporary buffer.
+ //
+ ucs2_char* d (static_cast<ucs2_char*> (tmp_buf));
+ const wchar_t* s (static_cast<const wchar_t*> (context) + *pos);
+
+ size_t n (0);
+ tmp_capacity /= 2; // In UCS-2 character.
+ for (const wchar_t* e (s + N);
+ s != e && *s != L'\0' && n != tmp_capacity;
+ ++n, ++s)
+ d[n] = static_cast<ucs2_char> (*s);
+
+ *buffer = d;
+ *size = n * 2; // In bytes.
+ *chunk = (n != tmp_capacity ? chunk_last : chunk_next);
+ if (*pos == 0)
+ {
+ if (*chunk == chunk_last)
+ *chunk = chunk_one;
+ else
+ *chunk = chunk_first;
+ }
+
+ *pos += n;
+ }
+
+ template <std::size_t N>
+ void c_warray_long_value_traits_base<N, 4>::
+ result_callback (void* context,
+ std::size_t* pos,
+ void** buffer,
+ std::size_t* size,
+ chunk_type chunk,
+ std::size_t,
+ void* tmp_buf,
+ std::size_t tmp_capacity)
+ {
+ wchar_t* d (static_cast<wchar_t*> (context));
+ const ucs2_char* s (static_cast<const ucs2_char*> (tmp_buf));
+
+ // Again, we cannot do direct buffer copy and have to use the
+ // temporary buffer instead.
+ //
+ switch (chunk)
+ {
+ case chunk_null:
+ case chunk_one:
+ {
+ *d = L'\0';
+ break;
+ }
+ case chunk_first:
+ {
+ break;
+ }
+ case chunk_next:
+ case chunk_last:
+ {
+ // Append the data from the temporary buffer.
+ //
+ if (*pos < N)
+ {
+ *size /= 2; // In UCS-2 characters.
+ size_t n (N - *pos);
+ n = *size < n ? *size : n;
+
+ wstring_functions<>::assign (d + *pos, s, n);
+ *pos += n;
+
+ if (*pos < N) // Append '\0' if there is space.
+ d[*pos] = L'\0';
+ }
+
+ break;
+ }
+ }
+
+ if (chunk == chunk_first || chunk == chunk_next)
+ {
+ *buffer = tmp_buf;
+ *size = tmp_capacity;
+ }
+ }
+#endif
+
+ //
+ // c_array_long_binary_value_traits
+ //
template <typename C, std::size_t N>
- void array_long_binary_value_traits<C, N>::
+ void c_array_long_binary_value_traits<C, N>::
param_callback (const void* context,
std::size_t*,
const void** buffer,
@@ -137,7 +352,7 @@ namespace odb
}
template <typename C, std::size_t N>
- void array_long_binary_value_traits<C, N>::
+ void c_array_long_binary_value_traits<C, N>::
result_callback (void* context,
std::size_t*,
void** buffer,
@@ -181,6 +396,5 @@ namespace odb
}
}
}
-#endif
}
}