From 742cf0608bf8232cf2fc8392a0f70855b0316755 Mon Sep 17 00:00:00 2001 From: Constantin Michael Date: Tue, 27 Sep 2011 09:29:54 +0200 Subject: Implement traits --- odb/oracle/makefile | 1 + odb/oracle/traits.cxx | 159 ++++++++ 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 // std::size_t +#include // std::memcpy, std::strlen +#include + #include + +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 (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 (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 (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 (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, id_blob> + // + bool default_value_traits, 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 (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 (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 + struct int_traits {static const bool unsign = false;}; + + template <> + struct int_traits {static const bool unsign = true;}; + template <> + struct int_traits {static const bool unsign = true;}; + template <> + struct int_traits {static const bool unsign = true;}; + template <> + struct int_traits {static const bool unsign = true;}; + template <> + struct int_traits {static const bool unsign = true;}; + template <> + struct int_traits + { + static const bool unsign = true; }; // // image_traits // - template + template struct image_traits; - template <> - struct image_traits {typedef int image_type;}; + // int32 + // + template + struct int32_image_traits; template <> - struct image_traits {typedef unsigned char[12] image_type;}; + struct int32_image_traits + { + typedef int image_type; + }; template <> - struct image_traits {typedef unsigned char[21] image_type;}; + struct int32_image_traits + { + typedef unsigned int image_type; + }; - template <> - struct image_traits {typedef float image_type;}; + template + struct image_traits: int32_image_traits::unsign> + { + }; - template <> - struct image_traits {typedef double image_type;}; + // int64 + // + template + struct int64_image_traits; template <> - struct image_traits {typedef unsigned char[21] image_type;}; + struct int64_image_traits + { + typedef long long image_type; + }; template <> - struct image_traits {typedef unsigned char[7] image_type;}; + struct int64_image_traits + { + typedef unsigned long long image_type; + }; - template <> - struct image_traits {typedef unsigned char* image_type;}; + template + struct image_traits: int64_image_traits::unsign> + { + }; - template <> - struct image_traits {typedef char* image_type;}; + // big_int + // + template + struct image_traits + { + // Image is a buffer containing native OCI NUMBER representation. + // + typedef char* image_type; + }; - template <> - struct image_traits {typedef char* image_type;}; + template + struct image_traits {typedef float image_type;}; - template <> - struct image_traits {typedef char* image_type;}; + template + struct image_traits {typedef double image_type;}; - template <> - struct image_traits {typedef lob_callback image_type;}; + template + struct image_traits + { + // Image is a buffer containing the native OCI NUMBER representation. + // + typedef char* image_type; + }; - template <> - struct image_traits {typedef lob_callback image_type;}; + template + struct image_traits + { + // 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 {typedef lob_callback image_type;}; + template + struct image_traits + { + // 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 + struct image_traits {typedef char* image_type;}; + + template + struct image_traits {typedef char* image_type;}; + + template + struct image_traits {typedef char* image_type;}; + + template + struct image_traits {typedef lob_callback image_type;}; + + template + struct image_traits {typedef lob_callback image_type;}; + + template + struct image_traits {typedef lob_callback image_type;}; // // value_traits @@ -114,360 +209,480 @@ namespace odb template ::r> struct select_traits; - // template - // struct select_traits - // { - // typedef default_value_traits type; - // }; - - // template - // struct select_traits - // { - // typedef - // wrapped_value_traits::null_handler> - // type; - // }; - - // template - // class value_traits: public select_traits::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 - // struct wrapped_value_traits - // { - // typedef wrapper_traits wtraits; - // typedef typename wtraits::wrapped_type wrapped_type; - - // typedef W value_type; - // typedef wrapped_type query_type; - // typedef typename image_traits::image_type image_type; - - // typedef value_traits 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 - // struct wrapped_value_traits - // { - // typedef wrapper_traits wtraits; - // typedef typename wtraits::wrapped_type wrapped_type; - - // typedef W value_type; - // typedef wrapped_type query_type; - // typedef typename image_traits::image_type image_type; - - // typedef value_traits 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 - // struct default_value_traits - // { - // typedef T value_type; - // typedef T query_type; - // typedef typename image_traits::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 - // struct default_value_traits - // { - // 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 (i - 1); - // else - // v = T (); - // } - - // static void - // set_image (unsigned short& i, bool& is_null, const T& v) - // { - // is_null = false; - // i = static_cast (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: - // string_value_traits - // { - // }; - - // template <> - // struct LIBODB_MYSQL_EXPORT default_value_traits: - // string_value_traits - // { - // }; - - // template <> - // struct LIBODB_MYSQL_EXPORT default_value_traits: - // string_value_traits - // { - // }; - - // template <> - // struct LIBODB_MYSQL_EXPORT default_value_traits: - // 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: - // c_string_value_traits - // { - // }; - - // template <> - // struct LIBODB_MYSQL_EXPORT default_value_traits: - // c_string_value_traits - // { - // }; - - // template <> - // struct LIBODB_MYSQL_EXPORT default_value_traits: - // c_string_value_traits - // { - // }; - - // template <> - // struct LIBODB_MYSQL_EXPORT default_value_traits: - // c_string_value_traits - // { - // }; - - // template - // struct default_value_traits: c_string_value_traits - // { - // }; - - // template - // struct default_value_traits: c_string_value_traits - // { - // }; - - // template - // struct default_value_traits: c_string_value_traits - // { - // }; - - // template - // struct default_value_traits: c_string_value_traits - // { - // }; - - // // std::vector (buffer) specialization. - // // - // template <> - // struct LIBODB_MYSQL_EXPORT default_value_traits, id_blob> - // { - // public: - // typedef std::vector value_type; - // typedef std::vector 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 + struct select_traits + { + typedef default_value_traits type; + }; + + template + struct select_traits + { + typedef + wrapped_value_traits::null_handler> + type; + }; + + template + class value_traits: public select_traits::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 + struct wrapped_value_traits + { + typedef wrapper_traits wtraits; + typedef typename wtraits::wrapped_type wrapped_type; + + typedef W value_type; + typedef wrapped_type query_type; + typedef typename image_traits::image_type image_type; + + typedef value_traits 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 + struct wrapped_value_traits + { + typedef wrapper_traits wtraits; + typedef typename wtraits::wrapped_type wrapped_type; + + typedef W value_type; + typedef wrapped_type query_type; + typedef typename image_traits::image_type image_type; + + typedef value_traits 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 + struct default_value_traits + { + typedef T value_type; + typedef T query_type; + typedef typename image_traits::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: + string_value_traits + { + }; + + template <> + struct LIBODB_ORACLE_EXPORT default_value_traits: + 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: + c_string_value_traits + { + }; + + template <> + struct LIBODB_ORACLE_EXPORT default_value_traits: + c_string_value_traits + { + }; + + template + struct default_value_traits: c_string_value_traits + { + }; + + template + struct default_value_traits: 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 (&v); + } + + static bool + result_callback (void* context, void* buffer, ub4 size, chunk_position p) + { + std::string& v (*reinterpret_cast (context)); + + switch (p) + { + case one_chunk: + case first_chunk: + { + v.clear (); + } + case next_chunk: + case last_chunk: + { + v.append (reinterpret_cast (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: + string_lob_value_traits + { + }; + + template <> + struct LIBODB_ORACLE_EXPORT default_value_traits: + 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 (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: + c_string_lob_value_traits + { + }; + + template <> + struct LIBODB_ORACLE_EXPORT default_value_traits: + c_string_lob_value_traits + { + }; + + template + struct default_value_traits: + c_string_lob_value_traits + { + }; + + template + struct default_value_traits: + c_string_lob_value_traits + { + }; + + // std::vector (buffer) specialization. + // + template <> + struct default_value_traits, id_blob> + { + public: + typedef std::vector value_type; + typedef std::vector 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 (&v); + } + + static bool + result_callback (void* context, void* buffer, ub4 size, chunk_position p) + { + value_type& v (*reinterpret_cast (context)); + + switch (p) + { + case one_chunk: + case first_chunk: + { + v.clear (); + } + case next_chunk: + case last_chunk: + { + char* b (reinterpret_cast (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 -- cgit v1.1