diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2011-04-18 18:50:04 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2011-04-18 18:50:04 +0200 |
commit | 6f4f07fea0f98bdb1debffcc40a32d6af61ab5c0 (patch) | |
tree | 525de2a9e700871befc4ff92ed814cbccf5d27c1 | |
parent | 1e1a40eb86919a19b0c6738741be50ec084be596 (diff) |
Implement automatic mapping for C++ enums
-rw-r--r-- | odb/mysql/enum.cxx | 34 | ||||
-rw-r--r-- | odb/mysql/enum.hxx | 131 | ||||
-rw-r--r-- | odb/mysql/makefile | 1 | ||||
-rw-r--r-- | odb/mysql/query.hxx | 17 | ||||
-rw-r--r-- | odb/mysql/traits.hxx | 31 |
5 files changed, 204 insertions, 10 deletions
diff --git a/odb/mysql/enum.cxx b/odb/mysql/enum.cxx new file mode 100644 index 0000000..d2c8676 --- /dev/null +++ b/odb/mysql/enum.cxx @@ -0,0 +1,34 @@ +// file : odb/mysql/enums.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include <cstring> // std::memmove +#include <cassert> + +#include <odb/mysql/enum.hxx> + +namespace odb +{ + namespace mysql + { + void enum_traits:: + strip_value (const details::buffer& i, unsigned long& size) + { + char* d (const_cast<char*> (i.data ())); + + unsigned long p (0); + for (; p < size && d[p] != ' '; ++p) ; + assert (p != size); + + p++; // Skip space; + size -= p; + + std::memmove (d, d + p, size); + } + } +} + +#include <odb/post.hxx> + +#endif // ODB_MYSQL_ENUMS_HXX diff --git a/odb/mysql/enum.hxx b/odb/mysql/enum.hxx new file mode 100644 index 0000000..95f4ed4 --- /dev/null +++ b/odb/mysql/enum.hxx @@ -0,0 +1,131 @@ +// file : odb/mysql/enums.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_MYSQL_ENUMS_HXX +#define ODB_MYSQL_ENUMS_HXX + +#include <odb/pre.hxx> + +#include <cstddef> // std::size_t +#include <cstring> // std::memmove +#include <cassert> + +#include <odb/details/buffer.hxx> + +#include <odb/mysql/mysql.hxx> +#include <odb/mysql/traits.hxx> +#include <odb/mysql/version.hxx> + +#include <odb/mysql/details/export.hxx> + +namespace odb +{ + namespace mysql + { + // Common interface for working with the dual enum image (integer or + // string). Used by the generated code and query machinery. + // + // We use overload resolution instead of template specialization to + // avoid having to specify the image type explicitly. + // + struct LIBODB_MYSQL_EXPORT enum_traits + { + // + // Integer image. + // + static void + bind (MYSQL_BIND& b, unsigned short& i, unsigned long&, my_bool* is_null) + { + b.buffer_type = MYSQL_TYPE_SHORT; + b.is_unsigned = 1; + b.buffer = &i; + b.is_null = is_null; + } + + static bool + grow (unsigned short&, unsigned long&) + { + return false; + } + + template <typename T> + static bool + set_image (unsigned short& i, unsigned long&, bool& is_null, const T& v) + { + value_traits<T, id_enum>::set_image (i, is_null, v); + return false; + } + + template <typename T> + static void + set_value (T& v, unsigned short i, unsigned long, bool is_null) + { + value_traits<T, id_enum>::set_value (v, i, is_null); + } + + // + // String image. + // + + static void + bind (MYSQL_BIND& b, + details::buffer& i, + unsigned long& size, + my_bool* is_null) + { + b.buffer_type = MYSQL_TYPE_STRING; + b.buffer = i.data (); + b.buffer_length = static_cast<unsigned long> (i.capacity ()); + b.length = &size; + b.is_null = is_null; + } + + static bool + grow (details::buffer& i, unsigned long& size) + { + i.capacity (size); + return true; + } + + template <typename T> + static bool + set_image (details::buffer& i, + unsigned long& size, + bool& is_null, + const T& v) + { + std::size_t n (0), c (i.capacity ()); + value_traits<T, id_enum>::set_image (i, n, is_null, v); + size = static_cast<unsigned long> (n); + return c != i.capacity (); + } + + template <typename T> + static void + set_value (T& v, + const details::buffer& i, + unsigned long size, + bool is_null) + { + // The buffer has the following content: "<num> <str>". Get rid of + // the numeric value so that we have "<str>". For more information + // why it is done this way, see mysql::object_columns class in the + // ODB compiler. + // + strip_value (i, size); + + value_traits<T, id_enum>::set_value (v, i, size, is_null); + } + + private: + void + strip_value (const details::buffer& i, unsigned long& size); + }; + } +} + +#include <odb/post.hxx> + +#endif // ODB_MYSQL_ENUMS_HXX diff --git a/odb/mysql/makefile b/odb/mysql/makefile index 018fd20..91eca19 100644 --- a/odb/mysql/makefile +++ b/odb/mysql/makefile @@ -9,6 +9,7 @@ cxx := \ connection.cxx \ connection-factory.cxx \ database.cxx \ +enum.cxx \ error.cxx \ exceptions.cxx \ object-statements.cxx \ diff --git a/odb/mysql/query.hxx b/odb/mysql/query.hxx index f4845cf..ca95f1c 100644 --- a/odb/mysql/query.hxx +++ b/odb/mysql/query.hxx @@ -18,6 +18,7 @@ #include <odb/mysql/version.hxx> #include <odb/mysql/forward.hxx> #include <odb/mysql/traits.hxx> +#include <odb/mysql/enum.hxx> #include <odb/mysql/binding.hxx> #include <odb/details/buffer.hxx> @@ -1676,6 +1677,8 @@ namespace odb // ENUM // + // The image type can be either integer or string. + // template <typename T> struct query_param_impl<T, id_enum>: query_param { @@ -1691,10 +1694,7 @@ namespace odb virtual void bind (MYSQL_BIND* b) { - b->buffer_type = MYSQL_TYPE_STRING; - b->buffer = buffer_.data (); - b->buffer_length = static_cast<unsigned long> (buffer_.capacity ()); - b->length = &size_; + enum_traits::bind (*b, image_, size_, 0); } private: @@ -1702,15 +1702,12 @@ namespace odb init (const T& v) { bool dummy; - std::size_t size, cap (buffer_.capacity ()); - value_traits<T, id_enum>::set_image (buffer_, size, dummy, v); - size_ = static_cast<unsigned long> (size); - return cap != buffer_.capacity (); + return enum_traits::set_image (image_, size_, dummy, v); } private: - details::buffer buffer_; - unsigned long size_; + typename value_traits<T, id_enum>::image_type image_; + unsigned long size_; // Keep size in case it is a string. }; // SET diff --git a/odb/mysql/traits.hxx b/odb/mysql/traits.hxx index 5418fa1..7f96c0b 100644 --- a/odb/mysql/traits.hxx +++ b/odb/mysql/traits.hxx @@ -162,6 +162,37 @@ namespace odb } }; + // 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 |