diff options
author | Constantin Michael <constantin@codesynthesis.com> | 2011-09-27 09:29:54 +0200 |
---|---|---|
committer | Constantin Michael <constantin@codesynthesis.com> | 2011-09-27 13:38:11 +0200 |
commit | 742cf0608bf8232cf2fc8392a0f70855b0316755 (patch) | |
tree | 6adacde0b07f484cbb0e8ab890d57bc5e67d72df | |
parent | 3eb25c0b2789aee57e006a92a25269b564789713 (diff) |
Implement traits
-rw-r--r-- | odb/oracle/makefile | 1 | ||||
-rw-r--r-- | odb/oracle/traits.cxx | 159 | ||||
-rw-r--r-- | odb/oracle/traits.hxx | 975 |
3 files changed, 755 insertions, 380 deletions
diff --git a/odb/oracle/makefile b/odb/oracle/makefile index 0725800..bd8d8cb 100644 --- a/odb/oracle/makefile +++ b/odb/oracle/makefile @@ -16,6 +16,7 @@ exceptions.cxx \ object-statements.cxx \ statement.cxx \ statements-base.cxx \ +traits.cxx \ transaction.cxx \ transaction-impl.cxx \ details/number.cxx diff --git a/odb/oracle/traits.cxx b/odb/oracle/traits.cxx index 16bfdee..6cf55c8 100644 --- a/odb/oracle/traits.cxx +++ b/odb/oracle/traits.cxx @@ -3,4 +3,163 @@ // copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC // license : ODB NCUEL; see accompanying LICENSE file +#include <cstddef> // std::size_t +#include <cstring> // std::memcpy, std::strlen +#include <cassert> + #include <odb/oracle/traits.hxx> + +using namespace std; + +namespace odb +{ + namespace oracle + { + // + // string_value_traits + // + + void string_value_traits:: + set_image (char* b, + size_t c, + size_t& n, + bool& is_null, + const string& v) + { + is_null = false; + n = v.size (); + + assert (n <= c); + + if (n != 0 && n <= c) + memcpy (b, v.c_str (), n); + } + + // + // c_string_value_traits + // + + void c_string_value_traits:: + set_image (char* b, + size_t c, + size_t& n, + bool& is_null, + const char* v) + { + is_null = false; + n = strlen (v); + + assert (n <= c); + + if (n != 0 && n <= c) + memcpy (b, v, n); + } + + // + // string_lob_value_traits + // + + bool string_lob_value_traits:: + param_callback (void* ctx, + ub4* pos_ctx, + void** b, + ub4* s, + chunk_position* p, + void* temp_b, + ub4 cap) + { + const string& v (*reinterpret_cast<string*> (ctx)); + + // @@ We rely on *pos_ctx == 0 for the first call. Make sure that this is + // set by the generated code, and update comment in oracle-types.hxx + // specifying that this is so. + // + *s = static_cast<ub4> (v.size ()) - *pos_ctx; + + if (*s <= cap) + *p = *pos_ctx == 0 ? one_chunk : last_chunk; + else + { + *p = *pos_ctx == 0 ? first_chunk : next_chunk; + *s = cap; + *pos_ctx += *s; + } + + *b = temp_b; + memcpy (temp_b, v.c_str () + *pos_ctx, *s); + + return true; + } + + // + // c_string_lob_value_traits + // + + bool c_string_lob_value_traits:: + param_callback (void* ctx, + ub4* pos_ctx, + void** b, + ub4* s, + chunk_position* p, + void* temp_b, + ub4 cap) + { + const char* v (reinterpret_cast<char*> (ctx)); + + // @@ We rely on *pos_ctx == 0 for the first call. Make sure that this is + // set by the generated code, and update comment in oracle-types.hxx + // specifying that this is so. + // + *s = static_cast<ub4> (strlen (v)) - *pos_ctx; + + if (*s <= cap) + *p = *pos_ctx == 0 ? one_chunk : last_chunk; + else + { + *p = *pos_ctx == 0 ? first_chunk : next_chunk; + *s = cap; + *pos_ctx += *s; + } + + *b = temp_b; + memcpy (temp_b, v + *pos_ctx, *s); + + return true; + } + + // + // default_value_traits<std::vector<char>, id_blob> + // + bool default_value_traits<std::vector<char>, id_blob>:: + param_callback (void* ctx, + ub4* pos_ctx, + void** b, + ub4* s, + chunk_position* p, + void* temp_b, + ub4 cap) + { + const value_type& v (*reinterpret_cast<value_type*> (ctx)); + + // @@ We rely on *position_context == 0 for the first call. Make sure + // that this is set by the generated code and update the comment in + // oracle-types.hxx specifying that this is so. + // + *s = static_cast<ub4> (v.size ()) - *pos_ctx; + + if (*s <= cap) + *p = *pos_ctx == 0 ? one_chunk : last_chunk; + else + { + *p = *pos_ctx == 0 ? first_chunk : next_chunk; + *s = cap; + *pos_ctx += *s; + } + + *b = temp_b; + memcpy (temp_b, &v[*pos_ctx], *s); + + return true; + } + } +} diff --git a/odb/oracle/traits.hxx b/odb/oracle/traits.hxx index d3f006d..a05d74f 100644 --- a/odb/oracle/traits.hxx +++ b/odb/oracle/traits.hxx @@ -49,57 +49,152 @@ namespace odb id_blob, id_clob, - id_nclob, + id_nclob + }; + + // + // int_traits + // + + // Only mark fundamental unsigned integers as unsigned. In particular, + // treat enums as signed since in most cases and on most platforms the + // underlying integer type will be signed. On Windows with VC9 and up + // and with GCC, the __intN types are simply aliases for the respective + // standard integers so the below code will cover them as well. Also + // note that the ODB compiler performs a similar test, so if you change + // anything below you will probably also need to make a similar change + // there. + // + template <typename T> + struct int_traits {static const bool unsign = false;}; + + template <> + struct int_traits<bool> {static const bool unsign = true;}; + template <> + struct int_traits<unsigned char> {static const bool unsign = true;}; + template <> + struct int_traits<unsigned short> {static const bool unsign = true;}; + template <> + struct int_traits<unsigned int> {static const bool unsign = true;}; + template <> + struct int_traits<unsigned long> {static const bool unsign = true;}; + template <> + struct int_traits<unsigned long long> + { + static const bool unsign = true; }; // // image_traits // - template <database_type_id> + template <typename T, database_type_id> struct image_traits; - template <> - struct image_traits<id_int32> {typedef int image_type;}; + // int32 + // + template <bool unsign> + struct int32_image_traits; template <> - struct image_traits<id_int64> {typedef unsigned char[12] image_type;}; + struct int32_image_traits<false> + { + typedef int image_type; + }; template <> - struct image_traits<id_big_int> {typedef unsigned char[21] image_type;}; + struct int32_image_traits<true> + { + typedef unsigned int image_type; + }; - template <> - struct image_traits<id_float> {typedef float image_type;}; + template <typename T> + struct image_traits<T, id_int32>: int32_image_traits<int_traits<T>::unsign> + { + }; - template <> - struct image_traits<id_double> {typedef double image_type;}; + // int64 + // + template <bool unsign> + struct int64_image_traits; template <> - struct image_traits<id_big_float> {typedef unsigned char[21] image_type;}; + struct int64_image_traits<false> + { + typedef long long image_type; + }; template <> - struct image_traits<id_date> {typedef unsigned char[7] image_type;}; + struct int64_image_traits<true> + { + typedef unsigned long long image_type; + }; - template <> - struct image_traits<id_timestamp> {typedef unsigned char* image_type;}; + template <typename T> + struct image_traits<T, id_int64>: int64_image_traits<int_traits<T>::unsign> + { + }; - template <> - struct image_traits<id_string> {typedef char* image_type;}; + // big_int + // + template <typename T> + struct image_traits<T, id_big_int> + { + // Image is a buffer containing native OCI NUMBER representation. + // + typedef char* image_type; + }; - template <> - struct image_traits<id_nstring> {typedef char* image_type;}; + template <typename T> + struct image_traits<T, id_float> {typedef float image_type;}; - template <> - struct image_traits<id_raw> {typedef char* image_type;}; + template <typename T> + struct image_traits<T, id_double> {typedef double image_type;}; - template <> - struct image_traits<id_blob> {typedef lob_callback image_type;}; + template <typename T> + struct image_traits<T, id_big_float> + { + // Image is a buffer containing the native OCI NUMBER representation. + // + typedef char* image_type; + }; - template <> - struct image_traits<id_clob> {typedef lob_callback image_type;}; + template <typename T> + struct image_traits<T, id_date> + { + // Image is a buffer containing the native OCI DATE representation. This + // buffer has a fixed length of 7 bytes. + // + typedef char* image_type; + }; - template <> - struct image_traits<id_nclob> {typedef lob_callback image_type;}; + template <typename T> + struct image_traits<T, id_timestamp> + { + // Image is a buffer containing the native OCI TIMESTAMP representation. + // This buffer has varying length, depending on the microsecond + // precision of the TIMESTAMP value. + // + typedef char* image_type; + }; + + template <typename T> + struct image_traits<T, id_string> {typedef char* image_type;}; + + template <typename T> + struct image_traits<T, id_nstring> {typedef char* image_type;}; + + template <typename T> + struct image_traits<T, id_raw> {typedef char* image_type;}; + + template <typename T> + struct image_traits<T, id_blob> {typedef lob_callback image_type;}; + + template <typename T> + struct image_traits<T, id_clob> {typedef lob_callback image_type;}; + + template <typename T> + struct image_traits<T, id_nclob> {typedef lob_callback image_type;}; // // value_traits @@ -114,360 +209,480 @@ namespace odb template <typename T, database_type_id, bool w = details::wrapper_p<T>::r> struct select_traits; - // template <typename T, database_type_id ID> - // struct select_traits<T, ID, false> - // { - // typedef default_value_traits<T, ID> type; - // }; - - // template <typename W, database_type_id ID> - // struct select_traits<W, ID, true> - // { - // typedef - // wrapped_value_traits<W, ID, wrapper_traits<W>::null_handler> - // type; - // }; - - // template <typename T, database_type_id ID> - // class value_traits: public select_traits<T, ID>::type - // { - // }; - - // // The wrapped_value_traits specializations should be able to handle - // // any value type which means we have to have every possible signature - // // of the set_value() and set_image() functions. - // // - // template <typename W, database_type_id ID> - // struct wrapped_value_traits<W, ID, false> - // { - // typedef wrapper_traits<W> wtraits; - // typedef typename wtraits::wrapped_type wrapped_type; - - // typedef W value_type; - // typedef wrapped_type query_type; - // typedef typename image_traits<ID>::image_type image_type; - - // typedef value_traits<wrapped_type, ID> vtraits; - - // static void - // set_value (W& v, const image_type& i, bool is_null) - // { - // vtraits::set_value (wtraits::set_ref (v), i, is_null); - // } - - // static void - // set_image (image_type& i, bool& is_null, const W& v) - // { - // vtraits::set_image (i, is_null, wtraits::get_ref (v)); - // } - - // // String, BLOB, ENUM, and SET. - // // - // static void - // set_value (W& v, const details::buffer& b, std::size_t n, bool is_null) - // { - // vtraits::set_value (wtraits::set_ref (v), b, n, is_null); - // } - - // static void - // set_image (details::buffer& b, std::size_t& n, bool& is_null, const W& v) - // { - // vtraits::set_image (b, n, is_null, wtraits::get_ref (v)); - // } - - // // BIT. - // // - // static void - // set_value (W& v, const unsigned char* i, std::size_t n, bool is_null) - // { - // vtraits::set_value (wtraits::set_ref (v), i, n, is_null); - // } - - // static void - // set_image (unsigned char* i, - // std::size_t c, - // std::size_t& n, - // bool& is_null, - // const W& v) - // { - // vtraits::set_image (i, c, n, is_null, wtraits::get_ref (v)); - // } - // }; - - // template <typename W, database_type_id ID> - // struct wrapped_value_traits<W, ID, true> - // { - // typedef wrapper_traits<W> wtraits; - // typedef typename wtraits::wrapped_type wrapped_type; - - // typedef W value_type; - // typedef wrapped_type query_type; - // typedef typename image_traits<ID>::image_type image_type; - - // typedef value_traits<wrapped_type, ID> vtraits; - - // static void - // set_value (W& v, const image_type& i, bool is_null) - // { - // if (is_null) - // wtraits::set_null (v); - // else - // vtraits::set_value (wtraits::set_ref (v), i, is_null); - // } - - // static void - // set_image (image_type& i, bool& is_null, const W& v) - // { - // is_null = wtraits::get_null (v); - - // if (!is_null) - // vtraits::set_image (i, is_null, wtraits::get_ref (v)); - // } - - // // String, BLOB, ENUM, and SET. - // // - // static void - // set_value (W& v, const details::buffer& b, std::size_t n, bool is_null) - // { - // if (is_null) - // wtraits::set_null (v); - // else - // vtraits::set_value (wtraits::set_ref (v), b, n, is_null); - // } - - // static void - // set_image (details::buffer& b, std::size_t& n, bool& is_null, const W& v) - // { - // is_null = wtraits::get_null (v); - - // if (!is_null) - // vtraits::set_image (b, n, is_null, wtraits::get_ref (v)); - // } - - // // BIT. - // // - // static void - // set_value (W& v, const unsigned char* i, std::size_t n, bool is_null) - // { - // if (is_null) - // wtraits::set_null (v); - // else - // vtraits::set_value (wtraits::set_ref (v), i, n, is_null); - // } - - // static void - // set_image (unsigned char* i, - // std::size_t c, - // std::size_t& n, - // bool& is_null, - // const W& v) - // { - // is_null = wtraits::get_null (v); - - // if (!is_null) - // vtraits::set_image (i, c, n, is_null, wtraits::get_ref (v)); - // } - // }; - - // template <typename T, database_type_id ID> - // struct default_value_traits - // { - // typedef T value_type; - // typedef T query_type; - // typedef typename image_traits<ID>::image_type image_type; - - // static void - // set_value (T& v, const image_type& i, bool is_null) - // { - // if (!is_null) - // v = T (i); - // else - // v = T (); - // } - - // static void - // set_image (image_type& i, bool& is_null, T v) - // { - // is_null = false; - // i = image_type (v); - // } - // }; - - // // Specialization for numeric enum representations (C++ enum, integer - // // types, etc). In particular, this specialization works only for C++ - // // enum type as long as its numeric value space starts with 0, is - // // ascending and contiguous (i.e., the default enumerator assignment). - // // - // template <typename T> - // struct default_value_traits<T, id_enum> - // { - // typedef T value_type; - // typedef T query_type; - // typedef unsigned short image_type; - - // static void - // set_value (T& v, unsigned short i, bool is_null) - // { - // // In MySQL first enumerator has index 1. - // // - // if (!is_null) - // v = static_cast<T> (i - 1); - // else - // v = T (); - // } - - // static void - // set_image (unsigned short& i, bool& is_null, const T& v) - // { - // is_null = false; - // i = static_cast<unsigned short> (v) + 1; - // } - // }; - - // // std::string specialization. - // // - // class LIBODB_MYSQL_EXPORT string_value_traits - // { - // public: - // typedef std::string value_type; - // typedef std::string query_type; - // typedef details::buffer image_type; - - // static void - // set_value (std::string& v, - // const details::buffer& b, - // std::size_t n, - // bool is_null) - // { - // if (!is_null) - // v.assign (b.data (), n); - // else - // v.erase (); - // } - - // static void - // set_image (details::buffer&, - // std::size_t& n, - // bool& is_null, - // const std::string&); - // }; - - // template <> - // struct LIBODB_MYSQL_EXPORT default_value_traits<std::string, id_string>: - // string_value_traits - // { - // }; - - // template <> - // struct LIBODB_MYSQL_EXPORT default_value_traits<std::string, id_decimal>: - // string_value_traits - // { - // }; - - // template <> - // struct LIBODB_MYSQL_EXPORT default_value_traits<std::string, id_enum>: - // string_value_traits - // { - // }; - - // template <> - // struct LIBODB_MYSQL_EXPORT default_value_traits<std::string, id_set>: - // string_value_traits - // { - // }; - - // // 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 - // // we can pass such values to the queries. - // // - // class LIBODB_MYSQL_EXPORT c_string_value_traits - // { - // public: - // typedef const char* value_type; - // typedef const char* query_type; - // typedef details::buffer image_type; - - // static void - // set_image (details::buffer&, - // std::size_t& n, - // bool& is_null, - // const char*); - // }; - - // template <> - // struct LIBODB_MYSQL_EXPORT default_value_traits<const char*, id_string>: - // c_string_value_traits - // { - // }; - - // template <> - // struct LIBODB_MYSQL_EXPORT default_value_traits<const char*, id_decimal>: - // c_string_value_traits - // { - // }; - - // template <> - // struct LIBODB_MYSQL_EXPORT default_value_traits<const char*, id_enum>: - // c_string_value_traits - // { - // }; - - // template <> - // struct LIBODB_MYSQL_EXPORT default_value_traits<const char*, id_set>: - // c_string_value_traits - // { - // }; - - // template <std::size_t n> - // struct default_value_traits<char[n], id_string>: c_string_value_traits - // { - // }; - - // template <std::size_t n> - // struct default_value_traits<char[n], id_decimal>: c_string_value_traits - // { - // }; - - // template <std::size_t n> - // struct default_value_traits<char[n], id_enum>: c_string_value_traits - // { - // }; - - // template <std::size_t n> - // struct default_value_traits<char[n], id_set>: c_string_value_traits - // { - // }; - - // // std::vector<char> (buffer) specialization. - // // - // template <> - // struct LIBODB_MYSQL_EXPORT default_value_traits<std::vector<char>, id_blob> - // { - // public: - // typedef std::vector<char> value_type; - // typedef std::vector<char> 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) - // { - // if (!is_null) - // v.assign (b.data (), b.data () + n); - // else - // v.clear (); - // } - - // static void - // set_image (details::buffer&, - // std::size_t& n, - // bool& is_null, - // const value_type&); - // }; + template <typename T, database_type_id ID> + struct select_traits<T, ID, false> + { + typedef default_value_traits<T, ID> type; + }; + + template <typename W, database_type_id ID> + struct select_traits<W, ID, true> + { + typedef + wrapped_value_traits<W, ID, wrapper_traits<W>::null_handler> + type; + }; + + template <typename T, database_type_id ID> + class value_traits: public select_traits<T, ID>::type + { + }; + + // The wrapped_value_traits specializations should be able to handle + // any value type which means we have to have every possible signature + // of the set_value() and set_image() functions. + // + template <typename W, database_type_id ID> + struct wrapped_value_traits<W, ID, false> + { + typedef wrapper_traits<W> wtraits; + typedef typename wtraits::wrapped_type wrapped_type; + + typedef W value_type; + typedef wrapped_type query_type; + typedef typename image_traits<wrapped_type, ID>::image_type image_type; + + typedef value_traits<wrapped_type, ID> vtraits; + + static void + set_value (W& v, const image_type& i, bool is_null) + { + vtraits::set_value (wtraits::set_ref (v), i, is_null); + } + + static void + set_image (image_type& i, bool& is_null, const W& v) + { + vtraits::set_image (i, is_null, wtraits::get_ref (v)); + } + + // big_int, big_float, timestamp, string, nstring, raw. + // + static void + set_value (W& v, const char* i, std::size_t n, bool is_null) + { + vtraits::set_value (wtraits::set_ref (v), i, n, is_null); + } + + static void + set_image (char* i, + std::size_t c, + std::size_t& n, + bool& is_null, + const W& v) + { + vtraits::set_image (i, c, n, is_null, wtraits::get_ref (v)); + } + + // blob, clob, nclob. + // + static void + set_value (W& v, result_callback_type& cb, void*& context, bool is_null) + { + vtraits::set_value (wtraits::set_ref (v), cb, context, is_null); + } + + static void + set_image (param_callback_type& cb, + void*& context, + bool& is_null, + const W& v) + { + vtraits::set_image (cb, context, is_null, wtraits::get_ref (v)); + } + }; + + template <typename W, database_type_id ID> + struct wrapped_value_traits<W, ID, true> + { + typedef wrapper_traits<W> wtraits; + typedef typename wtraits::wrapped_type wrapped_type; + + typedef W value_type; + typedef wrapped_type query_type; + typedef typename image_traits<wrapped_type, ID>::image_type image_type; + + typedef value_traits<wrapped_type, ID> vtraits; + + static void + set_value (W& v, const image_type& i, bool is_null) + { + if (is_null) + wtraits::set_null (v); + else + vtraits::set_value (wtraits::set_ref (v), i, is_null); + } + + static void + set_image (image_type& i, bool& is_null, const W& v) + { + is_null = wtraits::get_null (v); + + if (!is_null) + vtraits::set_image (i, is_null, wtraits::get_ref (v)); + } + + // big_int, big_float, timestamp, string, nstring, raw. + // + static void + set_value (W& v, const char* i, std::size_t n, bool is_null) + { + if (is_null) + wtraits::set_null (v); + else + vtraits::set_value (wtraits::set_ref (v), i, n, is_null); + } + + static void + set_image (char* i, + std::size_t c, + std::size_t& n, + bool& is_null, + const W& v) + { + is_null = wtraits::get_null (v); + + if (!is_null) + vtraits::set_image (i, c, n, is_null, wtraits::get_ref (v)); + } + + // blob, clob, nclob. + // + static void + set_value (W& v, result_callback_type& cb, void*& context, bool is_null) + { + if (is_null) + wtraits::set_null (v); + else + vtraits::set_value (wtraits::set_ref (v), cb, context, is_null); + } + + static void + set_image (param_callback_type& cb, + void*& context, + bool& is_null, + const W& v) + { + is_null = wtraits::get_null (v); + + if (!is_null) + vtraits::set_image (cb, context, is_null, wtraits::get_ref (v)); + } + }; + + template <typename T, database_type_id ID> + struct default_value_traits + { + typedef T value_type; + typedef T query_type; + typedef typename image_traits<T, ID>::image_type image_type; + + static void + set_value (T& v, const image_type& i, bool is_null) + { + if (!is_null) + v = T (i); + else + v = T (); + } + + static void + set_image (image_type& i, bool& is_null, T v) + { + is_null = false; + i = image_type (v); + } + }; + + // std::string specialization. + // + class LIBODB_ORACLE_EXPORT string_value_traits + { + public: + typedef std::string value_type; + typedef std::string query_type; + typedef char* image_type; + + static void + set_value (std::string& v, + const char* b, + std::size_t n, + bool is_null) + { + if (!is_null) + v.assign (b, n); + else + v.erase (); + } + + static void + set_image (char*, + std::size_t c, + std::size_t& n, + bool& is_null, + const std::string&); + }; + + template <> + struct LIBODB_ORACLE_EXPORT default_value_traits<std::string, id_string>: + string_value_traits + { + }; + + template <> + struct LIBODB_ORACLE_EXPORT default_value_traits<std::string, id_nstring>: + string_value_traits + { + }; + + // 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 + // we can pass such values to the queries. + // + class LIBODB_ORACLE_EXPORT c_string_value_traits + { + public: + typedef const char* value_type; + typedef const char* query_type; + typedef char* image_type; + + static void + set_image (char*, + std::size_t c, + std::size_t& n, + bool& is_null, + const char*); + }; + + template <> + struct LIBODB_ORACLE_EXPORT default_value_traits<const char*, id_string>: + c_string_value_traits + { + }; + + template <> + struct LIBODB_ORACLE_EXPORT default_value_traits<const char*, id_nstring>: + c_string_value_traits + { + }; + + template <std::size_t n> + struct default_value_traits<char[n], id_string>: c_string_value_traits + { + }; + + template <std::size_t n> + struct default_value_traits<char[n], id_nstring>: c_string_value_traits + { + }; + + // std::string specialization for LOBs. + // + class string_lob_value_traits + { + public: + typedef std::string value_type; + typedef std::string query_type; + typedef lob_callback image_type; + + static void + set_value (std::string& v, + result_callback_type& cb, + void*& context, + bool is_null) + { + if (!is_null) + { + cb = &result_callback; + context = &v; + } + else + v.erase (); + } + + static void + set_image (param_callback_type& cb, + void*& context, + bool& is_null, + const std::string& v) + { + is_null = false; + cb = ¶m_callback; + context = const_cast<std::string*> (&v); + } + + static bool + result_callback (void* context, void* buffer, ub4 size, chunk_position p) + { + std::string& v (*reinterpret_cast<std::string*> (context)); + + switch (p) + { + case one_chunk: + case first_chunk: + { + v.clear (); + } + case next_chunk: + case last_chunk: + { + v.append (reinterpret_cast<char*> (buffer), size); + } + } + + return true; + } + + static bool + param_callback (void* context, + ub4* position_context, + void** buffer, + ub4* size, + chunk_position*, + void* temp_buffer, + ub4 capacity); + }; + + template <> + struct LIBODB_ORACLE_EXPORT default_value_traits<std::string, id_clob>: + string_lob_value_traits + { + }; + + template <> + struct LIBODB_ORACLE_EXPORT default_value_traits<std::string, id_nclob>: + string_lob_value_traits + { + }; + + // const char* specialization for LOBs. + // + // Specialization for const char* which only supports initialization + // of an image from the value but not the other way around. This way + // we can such values to the queries. + // + class c_string_lob_value_traits + { + public: + typedef const char* value_type; + typedef const char* query_type; + typedef lob_callback image_type; + + static void + set_image (param_callback_type& cb, + void*& context, + bool& is_null, + const char* v) + { + is_null = false; + cb = ¶m_callback; + context = const_cast<char*> (v); + } + + static bool + param_callback (void* context, + ub4* position_context, + void** buffer, + ub4* size, + chunk_position*, + void* temp_buffer, + ub4 capacity); + }; + + template <> + struct LIBODB_ORACLE_EXPORT default_value_traits<const char*, id_clob>: + c_string_lob_value_traits + { + }; + + template <> + struct LIBODB_ORACLE_EXPORT default_value_traits<const char*, id_nclob>: + c_string_lob_value_traits + { + }; + + template <std::size_t n> + struct default_value_traits<char[n], id_clob>: + c_string_lob_value_traits + { + }; + + template <std::size_t n> + struct default_value_traits<char[n], id_nclob>: + c_string_lob_value_traits + { + }; + + // std::vector<char> (buffer) specialization. + // + template <> + struct default_value_traits<std::vector<char>, id_blob> + { + public: + typedef std::vector<char> value_type; + typedef std::vector<char> query_type; + typedef lob_callback image_type; + + static void + set_value (value_type& v, + result_callback_type& cb, + void*& context, + bool is_null) + { + if (!is_null) + { + cb = &result_callback; + context = &v; + } + else + v.clear (); + } + + static void + set_image (param_callback_type& cb, + void*& context, + bool& is_null, + const value_type& v) + { + is_null = false; + cb = ¶m_callback; + context = const_cast<value_type*> (&v); + } + + static bool + result_callback (void* context, void* buffer, ub4 size, chunk_position p) + { + value_type& v (*reinterpret_cast<value_type*> (context)); + + switch (p) + { + case one_chunk: + case first_chunk: + { + v.clear (); + } + case next_chunk: + case last_chunk: + { + char* b (reinterpret_cast<char*> (buffer)); + v.insert (v.end (), b, b + size); + } + } + + return true; + } + + static bool + param_callback (void* context, + ub4* position_context, + void** buffer, + ub4* size, + chunk_position*, + void* temp_buffer, + ub4 capacity); + }; // // type_traits |