aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2011-04-18 18:50:04 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2011-04-18 18:50:04 +0200
commit6f4f07fea0f98bdb1debffcc40a32d6af61ab5c0 (patch)
tree525de2a9e700871befc4ff92ed814cbccf5d27c1
parent1e1a40eb86919a19b0c6738741be50ec084be596 (diff)
Implement automatic mapping for C++ enums
-rw-r--r--odb/mysql/enum.cxx34
-rw-r--r--odb/mysql/enum.hxx131
-rw-r--r--odb/mysql/makefile1
-rw-r--r--odb/mysql/query.hxx17
-rw-r--r--odb/mysql/traits.hxx31
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