From c0af27a770b1505ad6a1226f57f90642ce395296 Mon Sep 17 00:00:00 2001
From: Boris Kolpackov <boris@codesynthesis.com>
Date: Mon, 8 Oct 2012 16:09:07 +0200
Subject: Ground work for multi-database support

All generated code now includes database id. The database-specific
database class interface has been updated to include all the database
operations. The database-specific tests now use this interface.
---
 odb/mysql/database.cxx                      |  18 +-
 odb/mysql/database.hxx                      | 186 ++++++++++++
 odb/mysql/database.ixx                      | 383 +++++++++++++++++++++++++
 odb/mysql/forward.hxx                       |   3 +-
 odb/mysql/no-id-object-result.hxx           |   8 +-
 odb/mysql/no-id-object-result.txx           |   2 +-
 odb/mysql/no-id-object-statements.hxx       |   2 +-
 odb/mysql/polymorphic-object-result.hxx     |  13 +-
 odb/mysql/polymorphic-object-result.txx     |   6 +-
 odb/mysql/polymorphic-object-statements.hxx |   2 +-
 odb/mysql/query-const-expr.cxx              |   2 +-
 odb/mysql/query.cxx                         |  46 +--
 odb/mysql/query.hxx                         | 420 ++++++++++++++++------------
 odb/mysql/query.ixx                         |   4 +-
 odb/mysql/query.txx                         |  27 +-
 odb/mysql/simple-object-result.hxx          |  10 +-
 odb/mysql/simple-object-result.txx          |   2 +-
 odb/mysql/simple-object-statements.hxx      |   4 +-
 odb/mysql/statement-cache.hxx               |   2 +-
 odb/mysql/statement-cache.txx               |   7 +-
 odb/mysql/view-result.hxx                   |   8 +-
 odb/mysql/view-result.txx                   |   2 +-
 odb/mysql/view-statements.hxx               |   2 +-
 23 files changed, 901 insertions(+), 258 deletions(-)

diff --git a/odb/mysql/database.cxx b/odb/mysql/database.cxx
index e7137bb..b80c95a 100644
--- a/odb/mysql/database.cxx
+++ b/odb/mysql/database.cxx
@@ -34,7 +34,8 @@ namespace odb
               const char* charset,
               unsigned long client_flags,
               transfer_ptr<connection_factory> factory)
-        : user_ (user ? user : ""),
+        : odb::database (id_mysql),
+          user_ (user ? user : ""),
           passwd_str_ (passwd ? passwd : ""),
           passwd_ (passwd ? passwd_str_.c_str () : 0),
           db_ (db ? db : ""),
@@ -62,7 +63,8 @@ namespace odb
               const string& charset,
               unsigned long client_flags,
               transfer_ptr<connection_factory> factory)
-        : user_ (user),
+        : odb::database (id_mysql),
+          user_ (user),
           passwd_str_ (passwd),
           passwd_ (passwd_str_.c_str ()),
           db_ (db),
@@ -90,7 +92,8 @@ namespace odb
               const string& charset,
               unsigned long client_flags,
               transfer_ptr<connection_factory> factory)
-        : user_ (user),
+        : odb::database (id_mysql),
+          user_ (user),
           passwd_str_ (passwd ? *passwd : ""),
           passwd_ (passwd ? passwd_str_.c_str () : 0),
           db_ (db),
@@ -118,7 +121,8 @@ namespace odb
               const string& charset,
               unsigned long client_flags,
               transfer_ptr<connection_factory> factory)
-        : user_ (user),
+        : odb::database (id_mysql),
+          user_ (user),
           passwd_str_ (passwd),
           passwd_ (passwd_str_.c_str ()),
           db_ (db),
@@ -146,7 +150,8 @@ namespace odb
               const string& charset,
               unsigned long client_flags,
               transfer_ptr<connection_factory> factory)
-        : user_ (user),
+        : odb::database (id_mysql),
+          user_ (user),
           passwd_str_ (passwd ? *passwd : ""),
           passwd_ (passwd ? passwd_str_.c_str () : 0),
           db_ (db),
@@ -171,7 +176,8 @@ namespace odb
               const string& charset,
               unsigned long client_flags,
               transfer_ptr<connection_factory> factory)
-        : passwd_ (0),
+        : odb::database (id_mysql),
+          passwd_ (0),
           socket_ (0),
           charset_ (charset),
           client_flags_ (client_flags),
diff --git a/odb/mysql/database.hxx b/odb/mysql/database.hxx
index 0008836..897134d 100644
--- a/odb/mysql/database.hxx
+++ b/odb/mysql/database.hxx
@@ -18,6 +18,7 @@
 #include <odb/mysql/mysql.hxx>
 #include <odb/mysql/version.hxx>
 #include <odb/mysql/forward.hxx>
+#include <odb/mysql/query.hxx>
 #include <odb/mysql/tracer.hxx>
 #include <odb/mysql/connection.hxx>
 #include <odb/mysql/connection-factory.hxx>
@@ -167,6 +168,191 @@ namespace odb
         return client_flags_;
       }
 
+      // Object persistence API.
+      //
+    public:
+
+      // Make the object persistent.
+      //
+      template <typename T>
+      typename object_traits<T>::id_type
+      persist (T& object);
+
+      template <typename T>
+      typename object_traits<T>::id_type
+      persist (T* obj_ptr);
+
+      template <typename T, template <typename> class P>
+      typename object_traits<T>::id_type
+      persist (const P<T>& obj_ptr);
+
+      template <typename T, typename A1, template <typename, typename> class P>
+      typename object_traits<T>::id_type
+      persist (const P<T, A1>& obj_ptr);
+
+      template <typename T, template <typename> class P>
+      typename object_traits<T>::id_type
+      persist (P<T>& obj_ptr);
+
+      template <typename T, typename A1, template <typename, typename> class P>
+      typename object_traits<T>::id_type
+      persist (P<T, A1>& obj_ptr);
+
+      template <typename T>
+      typename object_traits<T>::id_type
+      persist (const typename object_traits<T>::pointer_type& obj_ptr);
+
+      // Load an object. Throw object_not_persistent if not found.
+      //
+      template <typename T>
+      typename object_traits<T>::pointer_type
+      load (const typename object_traits<T>::id_type& id);
+
+      template <typename T>
+      void
+      load (const typename object_traits<T>::id_type& id, T& object);
+
+      // Reload an object.
+      //
+      template <typename T>
+      void
+      reload (T& object);
+
+      template <typename T>
+      void
+      reload (T* obj_ptr);
+
+      template <typename T, template <typename> class P>
+      void
+      reload (const P<T>& obj_ptr);
+
+      template <typename T, typename A1, template <typename, typename> class P>
+      void
+      reload (const P<T, A1>& obj_ptr);
+
+      template <typename T, template <typename> class P>
+      void
+      reload (P<T>& obj_ptr);
+
+      template <typename T, typename A1, template <typename, typename> class P>
+      void
+      reload (P<T, A1>& obj_ptr);
+
+      template <typename T>
+      void
+      reload (const typename object_traits<T>::pointer_type& obj_ptr);
+
+      // Loan an object if found. Return NULL/false if not found.
+      //
+      template <typename T>
+      typename object_traits<T>::pointer_type
+      find (const typename object_traits<T>::id_type& id);
+
+      template <typename T>
+      bool
+      find (const typename object_traits<T>::id_type& id, T& object);
+
+      // Update the state of a modified objects.
+      //
+      template <typename T>
+      void
+      update (T& object);
+
+      template <typename T>
+      void
+      update (T* obj_ptr);
+
+      template <typename T, template <typename> class P>
+      void
+      update (const P<T>& obj_ptr);
+
+      template <typename T, typename A1, template <typename, typename> class P>
+      void
+      update (const P<T, A1>& obj_ptr);
+
+      template <typename T, template <typename> class P>
+      void
+      update (P<T>& obj_ptr);
+
+      template <typename T, typename A1, template <typename, typename> class P>
+      void
+      update (P<T, A1>& obj_ptr);
+
+      template <typename T>
+      void
+      update (const typename object_traits<T>::pointer_type& obj_ptr);
+
+      // Make the object transient. Throw object_not_persistent if not
+      // found.
+      //
+      template <typename T>
+      void
+      erase (const typename object_traits<T>::id_type& id);
+
+      template <typename T>
+      void
+      erase (T& object);
+
+      template <typename T>
+      void
+      erase (T* obj_ptr);
+
+      template <typename T, template <typename> class P>
+      void
+      erase (const P<T>& obj_ptr);
+
+      template <typename T, typename A1, template <typename, typename> class P>
+      void
+      erase (const P<T, A1>& obj_ptr);
+
+      template <typename T, template <typename> class P>
+      void
+      erase (P<T>& obj_ptr);
+
+      template <typename T, typename A1, template <typename, typename> class P>
+      void
+      erase (P<T, A1>& obj_ptr);
+
+      template <typename T>
+      void
+      erase (const typename object_traits<T>::pointer_type& obj_ptr);
+
+      // Erase multiple objects matching a query predicate.
+      //
+      template <typename T>
+      unsigned long long
+      erase_query ();
+
+      template <typename T>
+      unsigned long long
+      erase_query (const char*);
+
+      template <typename T>
+      unsigned long long
+      erase_query (const std::string&);
+
+      template <typename T>
+      unsigned long long
+      erase_query (const mysql::query<T>&);
+
+      // Query API.
+      //
+      template <typename T>
+      result<T>
+      query (bool cache = true);
+
+      template <typename T>
+      result<T>
+      query (const char*, bool cache = true);
+
+      template <typename T>
+      result<T>
+      query (const std::string&, bool cache = true);
+
+      template <typename T>
+      result<T>
+      query (const mysql::query<T>&, bool cache = true);
+
     public:
       virtual transaction_impl*
       begin ();
diff --git a/odb/mysql/database.ixx b/odb/mysql/database.ixx
index d0a3d56..b69a301 100644
--- a/odb/mysql/database.ixx
+++ b/odb/mysql/database.ixx
@@ -15,5 +15,388 @@ namespace odb
       return connection_ptr (
         static_cast<mysql::connection*> (connection_ ()));
     }
+
+    template <typename T>
+    inline typename object_traits<T>::id_type database::
+    persist (T& obj)
+    {
+      return persist_<T, id_mysql> (obj);
+    }
+
+    template <typename T>
+    inline typename object_traits<T>::id_type database::
+    persist (T* p)
+    {
+      typedef typename object_traits<T>::pointer_type object_pointer;
+
+      // The passed pointer should be the same or implicit-convertible
+      // to the object pointer. This way we make sure the object pointer
+      // does not assume ownership of the passed object.
+      //
+      const object_pointer& pobj (p);
+
+      return persist_<T, id_mysql> (pobj);
+    }
+
+    template <typename T, template <typename> class P>
+    inline typename object_traits<T>::id_type database::
+    persist (const P<T>& p)
+    {
+      typedef typename object_traits<T>::pointer_type object_pointer;
+
+      // The passed pointer should be the same or implicit-convertible
+      // to the object pointer. This way we make sure the object pointer
+      // does not assume ownership of the passed object.
+      //
+      const object_pointer& pobj (p);
+
+      return persist_<T, id_mysql> (pobj);
+    }
+
+    template <typename T, typename A1, template <typename, typename> class P>
+    inline typename object_traits<T>::id_type database::
+    persist (const P<T, A1>& p)
+    {
+      typedef typename object_traits<T>::pointer_type object_pointer;
+
+      // The passed pointer should be the same or implicit-convertible
+      // to the object pointer. This way we make sure the object pointer
+      // does not assume ownership of the passed object.
+      //
+      const object_pointer& pobj (p);
+
+      return persist_<T, id_mysql> (pobj);
+    }
+
+    template <typename T, template <typename> class P>
+    inline typename object_traits<T>::id_type database::
+    persist (P<T>& p)
+    {
+      const P<T>& cr (p);
+      return persist<T, P> (cr);
+    }
+
+    template <typename T, typename A1, template <typename, typename> class P>
+    inline typename object_traits<T>::id_type database::
+    persist (P<T, A1>& p)
+    {
+      const P<T, A1>& cr (p);
+      return persist<T, A1, P> (cr);
+    }
+
+    template <typename T>
+    inline typename object_traits<T>::id_type database::
+    persist (const typename object_traits<T>::pointer_type& pobj)
+    {
+      return persist_<T, id_mysql> (pobj);
+    }
+
+    template <typename T>
+    inline typename object_traits<T>::pointer_type database::
+    load (const typename object_traits<T>::id_type& id)
+    {
+      return load_<T, id_mysql> (id);
+    }
+
+    template <typename T>
+    inline void database::
+    load (const typename object_traits<T>::id_type& id, T& obj)
+    {
+      return load_<T, id_mysql> (id, obj);
+    }
+
+    template <typename T>
+    inline typename object_traits<T>::pointer_type database::
+    find (const typename object_traits<T>::id_type& id)
+    {
+      return find_<T, id_mysql> (id);
+    }
+
+    template <typename T>
+    inline bool database::
+    find (const typename object_traits<T>::id_type& id, T& obj)
+    {
+      return find_<T, id_mysql> (id, obj);
+    }
+
+    template <typename T>
+    inline void database::
+    reload (T& obj)
+    {
+      reload_<T, id_mysql> (obj);
+    }
+
+    template <typename T>
+    inline void database::
+    reload (T* p)
+    {
+      reload<T> (*p);
+    }
+
+    template <typename T, template <typename> class P>
+    inline void database::
+    reload (const P<T>& p)
+    {
+      reload (odb::pointer_traits< P<T> >::get_ref (p));
+    }
+
+    template <typename T, typename A1, template <typename, typename> class P>
+    inline void database::
+    reload (const P<T, A1>& p)
+    {
+      reload (odb::pointer_traits< P<T, A1> >::get_ref (p));
+    }
+
+    template <typename T, template <typename> class P>
+    inline void database::
+    reload (P<T>& p)
+    {
+      reload (odb::pointer_traits< P<T> >::get_ref (p));
+    }
+
+    template <typename T, typename A1, template <typename, typename> class P>
+    inline void database::
+    reload (P<T, A1>& p)
+    {
+      reload (odb::pointer_traits< P<T, A1> >::get_ref (p));
+    }
+
+    template <typename T>
+    inline void database::
+    reload (const typename object_traits<T>::pointer_type& pobj)
+    {
+      typedef typename object_traits<T>::pointer_type pointer_type;
+
+      reload (odb::pointer_traits<pointer_type>::get_ref (pobj));
+    }
+
+    template <typename T>
+    inline void database::
+    update (T& obj)
+    {
+      update_<T, id_mysql> (obj);
+    }
+
+    template <typename T>
+    inline void database::
+    update (T* p)
+    {
+      typedef typename object_traits<T>::pointer_type object_pointer;
+
+      // The passed pointer should be the same or implicit-convertible
+      // to the object pointer. This way we make sure the object pointer
+      // does not assume ownership of the passed object.
+      //
+      const object_pointer& pobj (p);
+
+      update_<T, id_mysql> (pobj);
+    }
+
+    template <typename T, template <typename> class P>
+    inline void database::
+    update (const P<T>& p)
+    {
+      typedef typename object_traits<T>::pointer_type object_pointer;
+
+      // The passed pointer should be the same or implicit-convertible
+      // to the object pointer. This way we make sure the object pointer
+      // does not assume ownership of the passed object.
+      //
+      const object_pointer& pobj (p);
+
+      update_<T, id_mysql> (pobj);
+    }
+
+    template <typename T, typename A1, template <typename, typename> class P>
+    inline void database::
+    update (const P<T, A1>& p)
+    {
+      typedef typename object_traits<T>::pointer_type object_pointer;
+
+      // The passed pointer should be the same or implicit-convertible
+      // to the object pointer. This way we make sure the object pointer
+      // does not assume ownership of the passed object.
+      //
+      const object_pointer& pobj (p);
+
+      update_<T, id_mysql> (pobj);
+    }
+
+    template <typename T, template <typename> class P>
+    inline void database::
+    update (P<T>& p)
+    {
+      const P<T>& cr (p);
+      update<T, P> (cr);
+    }
+
+    template <typename T, typename A1, template <typename, typename> class P>
+    inline void database::
+    update (P<T, A1>& p)
+    {
+      const P<T, A1>& cr (p);
+      update<T, A1, P> (cr);
+    }
+
+    template <typename T>
+    inline void database::
+    update (const typename object_traits<T>::pointer_type& pobj)
+    {
+      update_<T, id_mysql> (pobj);
+    }
+
+    template <typename T>
+    inline void database::
+    erase (const typename object_traits<T>::id_type& id)
+    {
+      return erase_<T, id_mysql> (id);
+    }
+
+    template <typename T>
+    inline void database::
+    erase (T& obj)
+    {
+      return erase_<T, id_mysql> (obj);
+    }
+
+    template <typename T>
+    inline void database::
+    erase (T* p)
+    {
+      typedef typename object_traits<T>::pointer_type object_pointer;
+
+      // The passed pointer should be the same or implicit-convertible
+      // to the object pointer. This way we make sure the object pointer
+      // does not assume ownership of the passed object.
+      //
+      const object_pointer& pobj (p);
+
+      erase_<T, id_mysql> (pobj);
+    }
+
+    template <typename T, template <typename> class P>
+    inline void database::
+    erase (const P<T>& p)
+    {
+      typedef typename object_traits<T>::pointer_type object_pointer;
+
+      // The passed pointer should be the same or implicit-convertible
+      // to the object pointer. This way we make sure the object pointer
+      // does not assume ownership of the passed object.
+      //
+      const object_pointer& pobj (p);
+
+      erase_<T, id_mysql> (pobj);
+    }
+
+    template <typename T, typename A1, template <typename, typename> class P>
+    inline void database::
+    erase (const P<T, A1>& p)
+    {
+      typedef typename object_traits<T>::pointer_type object_pointer;
+
+      // The passed pointer should be the same or implicit-convertible
+      // to the object pointer. This way we make sure the object pointer
+      // does not assume ownership of the passed object.
+      //
+      const object_pointer& pobj (p);
+
+      erase_<T, id_mysql> (pobj);
+    }
+
+    template <typename T, template <typename> class P>
+    inline void database::
+    erase (P<T>& p)
+    {
+      const P<T>& cr (p);
+      erase<T, P> (cr);
+    }
+
+    template <typename T, typename A1, template <typename, typename> class P>
+    inline void database::
+    erase (P<T, A1>& p)
+    {
+      const P<T, A1>& cr (p);
+      erase<T, A1, P> (cr);
+    }
+
+    template <typename T>
+    inline void database::
+    erase (const typename object_traits<T>::pointer_type& pobj)
+    {
+      erase_<T, id_mysql> (pobj);
+    }
+
+    template <typename T>
+    inline unsigned long long database::
+    erase_query ()
+    {
+      // T is always object_type.
+      //
+      return erase_query<T> (mysql::query<T> ());
+    }
+
+    template <typename T>
+    inline unsigned long long database::
+    erase_query (const char* q)
+    {
+      // T is always object_type.
+      //
+      return erase_query<T> (mysql::query<T> (q));
+    }
+
+    template <typename T>
+    inline unsigned long long database::
+    erase_query (const std::string& q)
+    {
+      // T is always object_type.
+      //
+      return erase_query<T> (mysql::query<T> (q));
+    }
+
+    template <typename T>
+    inline unsigned long long database::
+    erase_query (const mysql::query<T>& q)
+    {
+      // T is always object_type.
+      //
+      return object_traits_impl<T, id_mysql>::erase_query (*this, q);
+    }
+
+    template <typename T>
+    inline result<T> database::
+    query (bool cache)
+    {
+      return query<T> (mysql::query<T> (), cache);
+    }
+
+    template <typename T>
+    inline result<T> database::
+    query (const char* q, bool cache)
+    {
+      return query<T> (mysql::query<T> (q), cache);
+    }
+
+    template <typename T>
+    inline result<T> database::
+    query (const std::string& q, bool cache)
+    {
+      return query<T> (mysql::query<T> (q), cache);
+    }
+
+    template <typename T>
+    inline result<T> database::
+    query (const mysql::query<T>& q, bool cache)
+    {
+      // T is always object_type. We also don't need to check for transaction
+      // here; object_traits::query () does this.
+      //
+      result<T> r (query_<T, id_mysql>::call (*this, q));
+
+      if (cache)
+        r.cache ();
+
+      return r;
+    }
   }
 }
diff --git a/odb/mysql/forward.hxx b/odb/mysql/forward.hxx
index 16bdc4c..7530329 100644
--- a/odb/mysql/forward.hxx
+++ b/odb/mysql/forward.hxx
@@ -20,7 +20,6 @@ namespace odb
     class statement;
     class transaction;
     class tracer;
-    class query;
 
     // Implementation details.
     //
@@ -51,6 +50,8 @@ namespace odb
 
     template <typename T>
     class container_statements;
+
+    class query_base;
   }
 
   namespace details
diff --git a/odb/mysql/no-id-object-result.hxx b/odb/mysql/no-id-object-result.hxx
index eb562bf..5907d20 100644
--- a/odb/mysql/no-id-object-result.hxx
+++ b/odb/mysql/no-id-object-result.hxx
@@ -14,7 +14,7 @@
 #include <odb/details/shared-ptr.hxx>
 
 #include <odb/mysql/version.hxx>
-#include <odb/mysql/forward.hxx> // query
+#include <odb/mysql/forward.hxx> // query_base
 #include <odb/mysql/statement.hxx>
 
 namespace odb
@@ -28,9 +28,9 @@ namespace odb
       typedef odb::no_id_object_result_impl<T> base_type;
 
       typedef typename base_type::object_type object_type;
-      typedef typename base_type::object_traits object_traits;
-
       typedef typename base_type::pointer_type pointer_type;
+
+      typedef object_traits_impl<object_type, id_mysql> object_traits;
       typedef typename base_type::pointer_traits pointer_traits;
 
       typedef typename object_traits::statements_type statements_type;
@@ -38,7 +38,7 @@ namespace odb
       virtual
       ~no_id_object_result_impl ();
 
-      no_id_object_result_impl (const query&,
+      no_id_object_result_impl (const query_base&,
                                 details::shared_ptr<select_statement>,
                                 statements_type&);
 
diff --git a/odb/mysql/no-id-object-result.txx b/odb/mysql/no-id-object-result.txx
index 0f996d1..530eeb7 100644
--- a/odb/mysql/no-id-object-result.txx
+++ b/odb/mysql/no-id-object-result.txx
@@ -21,7 +21,7 @@ namespace odb
 
     template <typename T>
     no_id_object_result_impl<T>::
-    no_id_object_result_impl (const query&,
+    no_id_object_result_impl (const query_base&,
                               details::shared_ptr<select_statement> statement,
                               statements_type& statements)
         : base_type (statements.connection ().database ()),
diff --git a/odb/mysql/no-id-object-statements.hxx b/odb/mysql/no-id-object-statements.hxx
index 89f736b..0778719 100644
--- a/odb/mysql/no-id-object-statements.hxx
+++ b/odb/mysql/no-id-object-statements.hxx
@@ -34,7 +34,7 @@ namespace odb
     {
     public:
       typedef T object_type;
-      typedef odb::object_traits<object_type> object_traits;
+      typedef object_traits_impl<object_type, id_mysql> object_traits;
       typedef typename object_traits::pointer_type pointer_type;
       typedef typename object_traits::image_type image_type;
 
diff --git a/odb/mysql/polymorphic-object-result.hxx b/odb/mysql/polymorphic-object-result.hxx
index 59bb74d..7749e14 100644
--- a/odb/mysql/polymorphic-object-result.hxx
+++ b/odb/mysql/polymorphic-object-result.hxx
@@ -14,7 +14,7 @@
 #include <odb/details/shared-ptr.hxx>
 
 #include <odb/mysql/version.hxx>
-#include <odb/mysql/forward.hxx> // query
+#include <odb/mysql/forward.hxx> // query_base
 #include <odb/mysql/statement.hxx>
 
 namespace odb
@@ -28,23 +28,24 @@ namespace odb
     public:
       typedef odb::polymorphic_object_result_impl<T> base_type;
 
-      typedef typename base_type::object_type object_type;
-      typedef typename base_type::object_traits object_traits;
       typedef typename base_type::id_type id_type;
-
+      typedef typename base_type::object_type object_type;
       typedef typename base_type::pointer_type pointer_type;
+
+      typedef object_traits_impl<object_type, id_mysql> object_traits;
       typedef typename base_type::pointer_traits pointer_traits;
 
       typedef typename base_type::root_type root_type;
-      typedef typename base_type::root_traits root_traits;
       typedef typename base_type::discriminator_type discriminator_type;
 
+      typedef object_traits_impl<root_type, id_mysql> root_traits;
+
       typedef typename object_traits::statements_type statements_type;
 
       virtual
       ~polymorphic_object_result_impl ();
 
-      polymorphic_object_result_impl (const query&,
+      polymorphic_object_result_impl (const query_base&,
                                       details::shared_ptr<select_statement>,
                                       statements_type&);
 
diff --git a/odb/mysql/polymorphic-object-result.txx b/odb/mysql/polymorphic-object-result.txx
index 1e341ff..518ff91 100644
--- a/odb/mysql/polymorphic-object-result.txx
+++ b/odb/mysql/polymorphic-object-result.txx
@@ -23,7 +23,7 @@ namespace odb
 
     template <typename T>
     polymorphic_object_result_impl<T>::
-    polymorphic_object_result_impl (const query&,
+    polymorphic_object_result_impl (const query_base&,
                                     details::shared_ptr<select_statement> st,
                                     statements_type& sts)
         : base_type (sts.connection ().database ()),
@@ -218,7 +218,7 @@ namespace odb
     {
       // Derived type version.
       //
-      typedef object_traits<T> traits;
+      typedef object_traits_impl<T, id_mysql> traits;
 
       static bool
       rebind (typename traits::statements_type& sts)
@@ -243,7 +243,7 @@ namespace odb
     {
       // Root type version.
       //
-      typedef object_traits<R> traits;
+      typedef object_traits_impl<R, id_mysql> traits;
 
       static bool
       rebind (typename traits::statements_type& sts)
diff --git a/odb/mysql/polymorphic-object-statements.hxx b/odb/mysql/polymorphic-object-statements.hxx
index 748e3ef..060654a 100644
--- a/odb/mysql/polymorphic-object-statements.hxx
+++ b/odb/mysql/polymorphic-object-statements.hxx
@@ -153,7 +153,7 @@ namespace odb
     {
     public:
       typedef T object_type;
-      typedef odb::object_traits<object_type> object_traits;
+      typedef object_traits_impl<object_type, id_mysql> object_traits;
       typedef typename object_traits::id_type id_type;
       typedef typename object_traits::pointer_type pointer_type;
       typedef typename object_traits::id_image_type id_image_type;
diff --git a/odb/mysql/query-const-expr.cxx b/odb/mysql/query-const-expr.cxx
index dd861c6..feb756e 100644
--- a/odb/mysql/query-const-expr.cxx
+++ b/odb/mysql/query-const-expr.cxx
@@ -10,6 +10,6 @@ namespace odb
   {
     // Sun CC cannot handle this in query.cxx.
     //
-    const query query::true_expr (true);
+    const query_base query_base::true_expr (true);
   }
 }
diff --git a/odb/mysql/query.cxx b/odb/mysql/query.cxx
index ac710d8..bc0c4f0 100644
--- a/odb/mysql/query.cxx
+++ b/odb/mysql/query.cxx
@@ -20,10 +20,10 @@ namespace odb
     {
     }
 
-    // query
+    // query_base
     //
-    query::
-    query (const query& q)
+    query_base::
+    query_base (const query_base& q)
         : clause_ (q.clause_),
           parameters_ (q.parameters_),
           bind_ (q.bind_),
@@ -43,8 +43,8 @@ namespace odb
       }
     }
 
-    query& query::
-    operator= (const query& q)
+    query_base& query_base::
+    operator= (const query_base& q)
     {
       if (this != &q)
       {
@@ -61,8 +61,8 @@ namespace odb
       return *this;
     }
 
-    query& query::
-    operator+= (const query& q)
+    query_base& query_base::
+    operator+= (const query_base& q)
     {
       clause_.insert (clause_.end (), q.clause_.begin (), q.clause_.end ());
 
@@ -84,7 +84,7 @@ namespace odb
       return *this;
     }
 
-    void query::
+    void query_base::
     append (const string& q)
     {
       if (!clause_.empty () && clause_.back ().kind == clause_part::native)
@@ -107,7 +107,7 @@ namespace odb
         clause_.push_back (clause_part (clause_part::native, q));
     }
 
-    void query::
+    void query_base::
     append (const char* table, const char* column)
     {
       string s (table);
@@ -117,7 +117,7 @@ namespace odb
       clause_.push_back (clause_part (clause_part::column, s));
     }
 
-    void query::
+    void query_base::
     add (details::shared_ptr<query_param> p, const char* conv)
     {
       clause_.push_back (clause_part (clause_part::param));
@@ -136,7 +136,7 @@ namespace odb
       p->bind (b);
     }
 
-    binding& query::
+    binding& query_base::
     parameters_binding () const
     {
       size_t n (parameters_.size ());
@@ -198,7 +198,7 @@ namespace odb
       return false;
     }
 
-    void query::
+    void query_base::
     optimize ()
     {
       // Remove a single TRUE literal or one that is followe by one of
@@ -218,7 +218,7 @@ namespace odb
       }
     }
 
-    const char* query::
+    const char* query_base::
     clause_prefix () const
     {
       if (!clause_.empty ())
@@ -234,7 +234,7 @@ namespace odb
       return "";
     }
 
-    string query::
+    string query_base::
     clause () const
     {
       string r;
@@ -306,8 +306,8 @@ namespace odb
       return clause_prefix () + r;
     }
 
-    query
-    operator&& (const query& x, const query& y)
+    query_base
+    operator&& (const query_base& x, const query_base& y)
     {
       // Optimize cases where one or both sides are constant truth.
       //
@@ -322,7 +322,7 @@ namespace odb
       if (yt)
         return x;
 
-      query r ("(");
+      query_base r ("(");
       r += x;
       r += ") AND (";
       r += y;
@@ -330,10 +330,10 @@ namespace odb
       return r;
     }
 
-    query
-    operator|| (const query& x, const query& y)
+    query_base
+    operator|| (const query_base& x, const query_base& y)
     {
-      query r ("(");
+      query_base r ("(");
       r += x;
       r += ") OR (";
       r += y;
@@ -341,10 +341,10 @@ namespace odb
       return r;
     }
 
-    query
-    operator! (const query& x)
+    query_base
+    operator! (const query_base& x)
     {
-      query r ("NOT (");
+      query_base r ("NOT (");
       r += x;
       r += ")";
       return r;
diff --git a/odb/mysql/query.hxx b/odb/mysql/query.hxx
index 74d8671..a38b5cb 100644
--- a/odb/mysql/query.hxx
+++ b/odb/mysql/query.hxx
@@ -82,7 +82,7 @@ namespace odb
     template <typename T, database_type_id ID>
     struct query_column;
 
-    class LIBODB_MYSQL_EXPORT query
+    class LIBODB_MYSQL_EXPORT query_base
     {
     public:
       struct clause_part
@@ -104,7 +104,7 @@ namespace odb
         bool bool_part;
       };
 
-      query ()
+      query_base ()
         : binding_ (0, 0)
       {
       }
@@ -112,27 +112,27 @@ namespace odb
       // True or false literal.
       //
       explicit
-      query (bool v)
+      query_base (bool v)
         : binding_ (0, 0)
       {
         clause_.push_back (clause_part (v));
       }
 
       explicit
-      query (const char* native)
+      query_base (const char* native)
         : binding_ (0, 0)
       {
         clause_.push_back (clause_part (clause_part::native, native));
       }
 
       explicit
-      query (const std::string& native)
+      query_base (const std::string& native)
         : binding_ (0, 0)
       {
         clause_.push_back (clause_part (clause_part::native, native));
       }
 
-      query (const char* table, const char* column)
+      query_base (const char* table, const char* column)
         : binding_ (0, 0)
       {
         append (table, column);
@@ -140,7 +140,7 @@ namespace odb
 
       template <typename T>
       explicit
-      query (val_bind<T> v)
+      query_base (val_bind<T> v)
         : binding_ (0, 0)
       {
         append<T, type_traits<T>::db_type_id> (
@@ -149,7 +149,7 @@ namespace odb
 
       template <typename T>
       explicit
-      query (ref_bind<T> r)
+      query_base (ref_bind<T> r)
         : binding_ (0, 0)
       {
         append<T, type_traits<T>::db_type_id> (
@@ -157,12 +157,12 @@ namespace odb
       }
 
       template <database_type_id ID>
-      query (const query_column<bool, ID>&);
+      query_base (const query_column<bool, ID>&);
 
-      query (const query&);
+      query_base (const query_base&);
 
-      query&
-      operator= (const query&);
+      query_base&
+      operator= (const query_base&);
 
     public:
       std::string
@@ -181,7 +181,7 @@ namespace odb
         return clause_.empty ();
       }
 
-      static const query true_expr;
+      static const query_base true_expr;
 
       bool
       const_true () const
@@ -210,10 +210,10 @@ namespace odb
       }
 
     public:
-      query&
-      operator+= (const query&);
+      query_base&
+      operator+= (const query_base&);
 
-      query&
+      query_base&
       operator+= (const std::string& q)
       {
         append (q);
@@ -221,7 +221,7 @@ namespace odb
       }
 
       template <typename T>
-      query&
+      query_base&
       operator+= (val_bind<T> v)
       {
         append<T, type_traits<T>::db_type_id> (
@@ -230,7 +230,7 @@ namespace odb
       }
 
       template <typename T>
-      query&
+      query_base&
       operator+= (ref_bind<T> r)
       {
         append<T, type_traits<T>::db_type_id> (
@@ -267,114 +267,114 @@ namespace odb
       mutable binding binding_;
     };
 
-    inline query
-    operator+ (const query& x, const query& y)
+    inline query_base
+    operator+ (const query_base& x, const query_base& y)
     {
-      query r (x);
+      query_base r (x);
       r += y;
       return r;
     }
 
     template <typename T>
-    inline query
-    operator+ (const query& q, val_bind<T> b)
+    inline query_base
+    operator+ (const query_base& q, val_bind<T> b)
     {
-      query r (q);
+      query_base r (q);
       r += b;
       return r;
     }
 
     template <typename T>
-    inline query
-    operator+ (const query& q, ref_bind<T> b)
+    inline query_base
+    operator+ (const query_base& q, ref_bind<T> b)
     {
-      query r (q);
+      query_base r (q);
       r += b;
       return r;
     }
 
     template <typename T>
-    inline query
-    operator+ (val_bind<T> b, const query& q)
+    inline query_base
+    operator+ (val_bind<T> b, const query_base& q)
     {
-      query r;
+      query_base r;
       r += b;
       r += q;
       return r;
     }
 
     template <typename T>
-    inline query
-    operator+ (ref_bind<T> b, const query& q)
+    inline query_base
+    operator+ (ref_bind<T> b, const query_base& q)
     {
-      query r;
+      query_base r;
       r += b;
       r += q;
       return r;
     }
 
-    inline query
-    operator+ (const query& q, const std::string& s)
+    inline query_base
+    operator+ (const query_base& q, const std::string& s)
     {
-      query r (q);
+      query_base r (q);
       r += s;
       return r;
     }
 
-    inline query
-    operator+ (const std::string& s, const query& q)
+    inline query_base
+    operator+ (const std::string& s, const query_base& q)
     {
-      query r (s);
+      query_base r (s);
       r += q;
       return r;
     }
 
     template <typename T>
-    inline query
+    inline query_base
     operator+ (const std::string& s, val_bind<T> b)
     {
-      query r (s);
+      query_base r (s);
       r += b;
       return r;
     }
 
     template <typename T>
-    inline query
+    inline query_base
     operator+ (const std::string& s, ref_bind<T> b)
     {
-      query r (s);
+      query_base r (s);
       r += b;
       return r;
     }
 
     template <typename T>
-    inline query
+    inline query_base
     operator+ (val_bind<T> b, const std::string& s)
     {
-      query r;
+      query_base r;
       r += b;
       r += s;
       return r;
     }
 
     template <typename T>
-    inline query
+    inline query_base
     operator+ (ref_bind<T> b, const std::string& s)
     {
-      query r;
+      query_base r;
       r += b;
       r += s;
       return r;
     }
 
-    LIBODB_MYSQL_EXPORT query
-    operator&& (const query& x, const query& y);
+    LIBODB_MYSQL_EXPORT query_base
+    operator&& (const query_base& x, const query_base& y);
 
-    LIBODB_MYSQL_EXPORT query
-    operator|| (const query& x, const query& y);
+    LIBODB_MYSQL_EXPORT query_base
+    operator|| (const query_base& x, const query_base& y);
 
-    LIBODB_MYSQL_EXPORT query
-    operator! (const query& x);
+    LIBODB_MYSQL_EXPORT query_base
+    operator! (const query_base& x);
 
     // query_column
     //
@@ -427,18 +427,18 @@ namespace odb
       // is_null, is_not_null
       //
     public:
-      query
+      query_base
       is_null () const
       {
-        query q (table_, column_);
+        query_base q (table_, column_);
         q += "IS NULL";
         return q;
       }
 
-      query
+      query_base
       is_not_null () const
       {
-        query q (table_, column_);
+        query_base q (table_, column_);
         q += "IS NOT NULL";
         return q;
       }
@@ -446,102 +446,102 @@ namespace odb
       // in
       //
     public:
-      query
+      query_base
       in (const T&, const T&) const;
 
-      query
+      query_base
       in (const T&, const T&, const T&) const;
 
-      query
+      query_base
       in (const T&, const T&, const T&, const T&) const;
 
-      query
+      query_base
       in (const T&, const T&, const T&, const T&, const T&) const;
 
       template <typename I>
-      query
+      query_base
       in_range (I begin, I end) const;
 
       // =
       //
     public:
-      query
+      query_base
       equal (const T& v) const
       {
         return equal (val_bind<T> (v));
       }
 
-      query
+      query_base
       equal (val_bind<T> v) const
       {
-        query q (table_, column_);
+        query_base q (table_, column_);
         q += "=";
         q.append<T, ID> (v, conversion_);
         return q;
       }
 
       template <typename T2>
-      query
+      query_base
       equal (val_bind<T2> v) const
       {
         copy_bind<T, T2> c (v.val);
         return equal (c);
       }
 
-      query
+      query_base
       equal (ref_bind<T> r) const
       {
-        query q (table_, column_);
+        query_base q (table_, column_);
         q += "=";
         q.append<T, ID> (r, conversion_);
         return q;
       }
 
-      friend query
+      friend query_base
       operator== (const query_column& c, const T& v)
       {
         return c.equal (v);
       }
 
-      friend query
+      friend query_base
       operator== (const T& v, const query_column& c)
       {
         return c.equal (v);
       }
 
-      friend query
+      friend query_base
       operator== (const query_column& c, val_bind<T> v)
       {
         return c.equal (v);
       }
 
-      friend query
+      friend query_base
       operator== (val_bind<T> v, const query_column& c)
       {
         return c.equal (v);
       }
 
       template <typename T2>
-      friend query
+      friend query_base
       operator== (const query_column& c, val_bind<T2> v)
       {
         return c.equal (v);
       }
 
       template <typename T2>
-      friend query
+      friend query_base
       operator== (val_bind<T2> v, const query_column& c)
       {
         return c.equal (v);
       }
 
-      friend query
+      friend query_base
       operator== (const query_column& c, ref_bind<T> r)
       {
         return c.equal (r);
       }
 
-      friend query
+      friend query_base
       operator== (ref_bind<T> r, const query_column& c)
       {
         return c.equal (r);
@@ -550,83 +550,83 @@ namespace odb
       // !=
       //
     public:
-      query
+      query_base
       unequal (const T& v) const
       {
         return unequal (val_bind<T> (v));
       }
 
-      query
+      query_base
       unequal (val_bind<T> v) const
       {
-        query q (table_, column_);
+        query_base q (table_, column_);
         q += "!=";
         q.append<T, ID> (v, conversion_);
         return q;
       }
 
       template <typename T2>
-      query
+      query_base
       unequal (val_bind<T2> v) const
       {
         copy_bind<T, T2> c (v.val);
         return unequal (c);
       }
 
-      query
+      query_base
       unequal (ref_bind<T> r) const
       {
-        query q (table_, column_);
+        query_base q (table_, column_);
         q += "!=";
         q.append<T, ID> (r, conversion_);
         return q;
       }
 
-      friend query
+      friend query_base
       operator!= (const query_column& c, const T& v)
       {
         return c.unequal (v);
       }
 
-      friend query
+      friend query_base
       operator!= (const T& v, const query_column& c)
       {
         return c.unequal (v);
       }
 
-      friend query
+      friend query_base
       operator!= (const query_column& c, val_bind<T> v)
       {
         return c.unequal (v);
       }
 
-      friend query
+      friend query_base
       operator!= (val_bind<T> v, const query_column& c)
       {
         return c.unequal (v);
       }
 
       template <typename T2>
-      friend query
+      friend query_base
       operator!= (const query_column& c, val_bind<T2> v)
       {
         return c.unequal (v);
       }
 
       template <typename T2>
-      friend query
+      friend query_base
       operator!= (val_bind<T2> v, const query_column& c)
       {
         return c.unequal (v);
       }
 
-      friend query
+      friend query_base
       operator!= (const query_column& c, ref_bind<T> r)
       {
         return c.unequal (r);
       }
 
-      friend query
+      friend query_base
       operator!= (ref_bind<T> r, const query_column& c)
       {
         return c.unequal (r);
@@ -635,83 +635,83 @@ namespace odb
       // <
       //
     public:
-      query
+      query_base
       less (const T& v) const
       {
         return less (val_bind<T> (v));
       }
 
-      query
+      query_base
       less (val_bind<T> v) const
       {
-        query q (table_, column_);
+        query_base q (table_, column_);
         q += "<";
         q.append<T, ID> (v, conversion_);
         return q;
       }
 
       template <typename T2>
-      query
+      query_base
       less (val_bind<T2> v) const
       {
         copy_bind<T, T2> c (v.val);
         return less (c);
       }
 
-      query
+      query_base
       less (ref_bind<T> r) const
       {
-        query q (table_, column_);
+        query_base q (table_, column_);
         q += "<";
         q.append<T, ID> (r, conversion_);
         return q;
       }
 
-      friend query
+      friend query_base
       operator< (const query_column& c, const T& v)
       {
         return c.less (v);
       }
 
-      friend query
+      friend query_base
       operator< (const T& v, const query_column& c)
       {
         return c.greater (v);
       }
 
-      friend query
+      friend query_base
       operator< (const query_column& c, val_bind<T> v)
       {
         return c.less (v);
       }
 
-      friend query
+      friend query_base
       operator< (val_bind<T> v, const query_column& c)
       {
         return c.greater (v);
       }
 
       template <typename T2>
-      friend query
+      friend query_base
       operator< (const query_column& c, val_bind<T2> v)
       {
         return c.less (v);
       }
 
       template <typename T2>
-      friend query
+      friend query_base
       operator< (val_bind<T2> v, const query_column& c)
       {
         return c.greater (v);
       }
 
-      friend query
+      friend query_base
       operator< (const query_column& c, ref_bind<T> r)
       {
         return c.less (r);
       }
 
-      friend query
+      friend query_base
       operator< (ref_bind<T> r, const query_column& c)
       {
         return c.greater (r);
@@ -720,83 +720,83 @@ namespace odb
       // >
       //
     public:
-      query
+      query_base
       greater (const T& v) const
       {
         return greater (val_bind<T> (v));
       }
 
-      query
+      query_base
       greater (val_bind<T> v) const
       {
-        query q (table_, column_);
+        query_base q (table_, column_);
         q += ">";
         q.append<T, ID> (v, conversion_);
         return q;
       }
 
       template <typename T2>
-      query
+      query_base
       greater (val_bind<T2> v) const
       {
         copy_bind<T, T2> c (v.val);
         return greater (c);
       }
 
-      query
+      query_base
       greater (ref_bind<T> r) const
       {
-        query q (table_, column_);
+        query_base q (table_, column_);
         q += ">";
         q.append<T, ID> (r, conversion_);
         return q;
       }
 
-      friend query
+      friend query_base
       operator> (const query_column& c, const T& v)
       {
         return c.greater (v);
       }
 
-      friend query
+      friend query_base
       operator> (const T& v, const query_column& c)
       {
         return c.less (v);
       }
 
-      friend query
+      friend query_base
       operator> (const query_column& c, val_bind<T> v)
       {
         return c.greater (v);
       }
 
-      friend query
+      friend query_base
       operator> (val_bind<T> v, const query_column& c)
       {
         return c.less (v);
       }
 
       template <typename T2>
-      friend query
+      friend query_base
       operator> (const query_column& c, val_bind<T2> v)
       {
         return c.greater (v);
       }
 
       template <typename T2>
-      friend query
+      friend query_base
       operator> (val_bind<T2> v, const query_column& c)
       {
         return c.less (v);
       }
 
-      friend query
+      friend query_base
       operator> (const query_column& c, ref_bind<T> r)
       {
         return c.greater (r);
       }
 
-      friend query
+      friend query_base
       operator> (ref_bind<T> r, const query_column& c)
       {
         return c.less (r);
@@ -805,83 +805,83 @@ namespace odb
       // <=
       //
     public:
-      query
+      query_base
       less_equal (const T& v) const
       {
         return less_equal (val_bind<T> (v));
       }
 
-      query
+      query_base
       less_equal (val_bind<T> v) const
       {
-        query q (table_, column_);
+        query_base q (table_, column_);
         q += "<=";
         q.append<T, ID> (v, conversion_);
         return q;
       }
 
       template <typename T2>
-      query
+      query_base
       less_equal (val_bind<T2> v) const
       {
         copy_bind<T, T2> c (v.val);
         return less_equal (c);
       }
 
-      query
+      query_base
       less_equal (ref_bind<T> r) const
       {
-        query q (table_, column_);
+        query_base q (table_, column_);
         q += "<=";
         q.append<T, ID> (r, conversion_);
         return q;
       }
 
-      friend query
+      friend query_base
       operator<= (const query_column& c, const T& v)
       {
         return c.less_equal (v);
       }
 
-      friend query
+      friend query_base
       operator<= (const T& v, const query_column& c)
       {
         return c.greater_equal (v);
       }
 
-      friend query
+      friend query_base
       operator<= (const query_column& c, val_bind<T> v)
       {
         return c.less_equal (v);
       }
 
-      friend query
+      friend query_base
       operator<= (val_bind<T> v, const query_column& c)
       {
         return c.greater_equal (v);
       }
 
       template <typename T2>
-      friend query
+      friend query_base
       operator<= (const query_column& c, val_bind<T2> v)
       {
         return c.less_equal (v);
       }
 
       template <typename T2>
-      friend query
+      friend query_base
       operator<= (val_bind<T2> v, const query_column& c)
       {
         return c.greater_equal (v);
       }
 
-      friend query
+      friend query_base
       operator<= (const query_column& c, ref_bind<T> r)
       {
         return c.less_equal (r);
       }
 
-      friend query
+      friend query_base
       operator<= (ref_bind<T> r, const query_column& c)
       {
         return c.greater_equal (r);
@@ -890,83 +890,83 @@ namespace odb
       // >=
       //
     public:
-      query
+      query_base
       greater_equal (const T& v) const
       {
         return greater_equal (val_bind<T> (v));
       }
 
-      query
+      query_base
       greater_equal (val_bind<T> v) const
       {
-        query q (table_, column_);
+        query_base q (table_, column_);
         q += ">=";
         q.append<T, ID> (v, conversion_);
         return q;
       }
 
       template <typename T2>
-      query
+      query_base
       greater_equal (val_bind<T2> v) const
       {
         copy_bind<T, T2> c (v.val);
         return greater_equal (c);
       }
 
-      query
+      query_base
       greater_equal (ref_bind<T> r) const
       {
-        query q (table_, column_);
+        query_base q (table_, column_);
         q += ">=";
         q.append<T, ID> (r, conversion_);
         return q;
       }
 
-      friend query
+      friend query_base
       operator>= (const query_column& c, const T& v)
       {
         return c.greater_equal (v);
       }
 
-      friend query
+      friend query_base
       operator>= (const T& v, const query_column& c)
       {
         return c.less_equal (v);
       }
 
-      friend query
+      friend query_base
       operator>= (const query_column& c, val_bind<T> v)
       {
         return c.greater_equal (v);
       }
 
-      friend query
+      friend query_base
       operator>= (val_bind<T> v, const query_column& c)
       {
         return c.less_equal (v);
       }
 
       template <typename T2>
-      friend query
+      friend query_base
       operator>= (const query_column& c, val_bind<T2> v)
       {
         return c.greater_equal (v);
       }
 
       template <typename T2>
-      friend query
+      friend query_base
       operator>= (val_bind<T2> v, const query_column& c)
       {
         return c.less_equal (v);
       }
 
-      friend query
+      friend query_base
       operator>= (const query_column& c, ref_bind<T> r)
       {
         return c.greater_equal (r);
       }
 
-      friend query
+      friend query_base
       operator>= (ref_bind<T> r, const query_column& c)
       {
         return c.less_equal (r);
@@ -976,84 +976,84 @@ namespace odb
       //
     public:
       template <typename T2, database_type_id ID2>
-      query
+      query_base
       operator== (const query_column<T2, ID2>& c) const
       {
         // We can compare columns only if we can compare their C++ types.
         //
         (void) (sizeof (type_instance<T> () == type_instance<T2> ()));
 
-        query q (table_, column_);
+        query_base q (table_, column_);
         q += "=";
         q.append (c.table (), c.column ());
         return q;
       }
 
       template <typename T2, database_type_id ID2>
-      query
+      query_base
       operator!= (const query_column<T2, ID2>& c) const
       {
         // We can compare columns only if we can compare their C++ types.
         //
         (void) (sizeof (type_instance<T> () != type_instance<T2> ()));
 
-        query q (table_, column_);
+        query_base q (table_, column_);
         q += "!=";
         q.append (c.table (), c.column ());
         return q;
       }
 
       template <typename T2, database_type_id ID2>
-      query
+      query_base
       operator< (const query_column<T2, ID2>& c) const
       {
         // We can compare columns only if we can compare their C++ types.
         //
         (void) (sizeof (type_instance<T> () < type_instance<T2> ()));
 
-        query q (table_, column_);
+        query_base q (table_, column_);
         q += "<";
         q.append (c.table (), c.column ());
         return q;
       }
 
       template <typename T2, database_type_id ID2>
-      query
+      query_base
       operator> (const query_column<T2, ID2>& c) const
       {
         // We can compare columns only if we can compare their C++ types.
         //
         (void) (sizeof (type_instance<T> () > type_instance<T2> ()));
 
-        query q (table_, column_);
+        query_base q (table_, column_);
         q += ">";
         q.append (c.table (), c.column ());
         return q;
       }
 
       template <typename T2, database_type_id ID2>
-      query
+      query_base
       operator<= (const query_column<T2, ID2>& c) const
       {
         // We can compare columns only if we can compare their C++ types.
         //
         (void) (sizeof (type_instance<T> () <= type_instance<T2> ()));
 
-        query q (table_, column_);
+        query_base q (table_, column_);
         q += "<=";
         q.append (c.table (), c.column ());
         return q;
       }
 
       template <typename T2, database_type_id ID2>
-      query
+      query_base
       operator>= (const query_column<T2, ID2>& c) const
       {
         // We can compare columns only if we can compare their C++ types.
         //
         (void) (sizeof (type_instance<T> () >= type_instance<T2> ()));
 
-        query q (table_, column_);
+        query_base q (table_, column_);
         q += ">=";
         q.append (c.table (), c.column ());
         return q;
@@ -1069,37 +1069,37 @@ namespace odb
     // query fragments (e.g., ORDER BY).
     //
     template <typename T, database_type_id ID>
-    inline query
+    inline query_base
     operator+ (const query_column<T, ID>& c, const std::string& s)
     {
-      query q (c.table (), c.column ());
+      query_base q (c.table (), c.column ());
       q += s;
       return q;
     }
 
     template <typename T, database_type_id ID>
-    inline query
+    inline query_base
     operator+ (const std::string& s, const query_column<T, ID>& c)
     {
-      query q (s);
+      query_base q (s);
       q.append (c.table (), c.column ());
       return q;
     }
 
     template <typename T, database_type_id ID>
-    inline query
-    operator+ (const query_column<T, ID>& c, const query& q)
+    inline query_base
+    operator+ (const query_column<T, ID>& c, const query_base& q)
     {
-      query r (c.table (), c.column ());
+      query_base r (c.table (), c.column ());
       r += q;
       return r;
     }
 
     template <typename T, database_type_id ID>
-    inline query
-    operator+ (const query& q, const query_column<T, ID>& c)
+    inline query_base
+    operator+ (const query_base& q, const query_column<T, ID>& c)
     {
-      query r (q);
+      query_base r (q);
       r.append (c.table (), c.column ());
       return r;
     }
@@ -1857,13 +1857,75 @@ namespace odb
   }
 }
 
-// odb::query specialization for MySQL.
+// odb::mysql::query and odb::query specialization for MySQL.
 //
 namespace odb
 {
+  namespace mysql
+  {
+    template <typename T>
+    class query: public query_base,
+                 public query_selector<T, id_mysql>::columns_type
+    {
+    public:
+      // We don't define any typedefs here since they may clash with
+      // column names defined by our base type.
+      //
+
+      query ()
+      {
+      }
+
+      explicit
+      query (bool v)
+          : query_base (v)
+      {
+      }
+
+      explicit
+      query (const char* q)
+          : query_base (q)
+      {
+      }
+
+      explicit
+      query (const std::string& q)
+          : query_base (q)
+      {
+      }
+
+      template <typename T2>
+      explicit
+      query (val_bind<T2> v)
+          : query_base (v)
+      {
+      }
+
+      template <typename T2>
+      explicit
+      query (ref_bind<T2> r)
+          : query_base (r)
+      {
+      }
+
+      query (const query_base& q)
+          : query_base (q)
+      {
+      }
+
+      template <database_type_id ID>
+      query (const query_column<bool, ID>& qc)
+          : query_base (qc)
+      {
+      }
+    };
+  }
+
+  // Derive odb::query from odb::mysql::query so that it can be
+  // implicitly converted in mysql::database::query() calls.
+  //
   template <typename T>
-  class query<T, mysql::query>: public mysql::query,
-                                public query_selector<T>::columns_type
+  class query<T, mysql::query_base>: public mysql::query<T>
   {
   public:
     // We don't define any typedefs here since they may clash with
@@ -1876,44 +1938,44 @@ namespace odb
 
     explicit
     query (bool v)
-        : mysql::query (v)
+        : mysql::query<T> (v)
     {
     }
 
     explicit
     query (const char* q)
-        : mysql::query (q)
+        : mysql::query<T> (q)
     {
     }
 
     explicit
     query (const std::string& q)
-        : mysql::query (q)
+        : mysql::query<T> (q)
     {
     }
 
     template <typename T2>
     explicit
     query (mysql::val_bind<T2> v)
-        : mysql::query (mysql::query (v))
+        : mysql::query<T> (v)
     {
     }
 
     template <typename T2>
     explicit
     query (mysql::ref_bind<T2> r)
-        : mysql::query (mysql::query (r))
+        : mysql::query<T> (r)
     {
     }
 
-    query (const mysql::query& q)
-        : mysql::query (q)
+    query (const mysql::query_base& q)
+        : mysql::query<T> (q)
     {
     }
 
     template <mysql::database_type_id ID>
     query (const mysql::query_column<bool, ID>& qc)
-        : mysql::query (qc)
+        : mysql::query<T> (qc)
     {
     }
   };
diff --git a/odb/mysql/query.ixx b/odb/mysql/query.ixx
index 2508ae3..ce485f1 100644
--- a/odb/mysql/query.ixx
+++ b/odb/mysql/query.ixx
@@ -7,7 +7,7 @@ namespace odb
   namespace mysql
   {
     template <typename T, database_type_id ID>
-    inline void query::
+    inline void query_base::
     append (val_bind<T> v, const char* conv)
     {
       add (
@@ -17,7 +17,7 @@ namespace odb
     }
 
     template <typename T, database_type_id ID>
-    inline void query::
+    inline void query_base::
     append (ref_bind<T> r, const char* conv)
     {
       add (
diff --git a/odb/mysql/query.txx b/odb/mysql/query.txx
index 80b6358..0dd0b9a 100644
--- a/odb/mysql/query.txx
+++ b/odb/mysql/query.txx
@@ -6,12 +6,12 @@ namespace odb
 {
   namespace mysql
   {
-    // query
+    // query_base
     //
 
     template <database_type_id ID>
-    query::
-    query (const query_column<bool, ID>& c)
+    query_base::
+    query_base (const query_column<bool, ID>& c)
         : binding_ (0, 0)
     {
       // Cannot use IS TRUE here since database type can be a non-
@@ -25,10 +25,10 @@ namespace odb
     // query_column
     //
     template <typename T, database_type_id ID>
-    query query_column<T, ID>::
+    query_base query_column<T, ID>::
     in (const T& v1, const T& v2) const
     {
-      query q (table_, column_);
+      query_base q (table_, column_);
       q += "IN (";
       q.append<T, ID> (val_bind<T> (v1), conversion_);
       q += ",";
@@ -38,10 +38,10 @@ namespace odb
     }
 
     template <typename T, database_type_id ID>
-    query query_column<T, ID>::
+    query_base query_column<T, ID>::
     in (const T& v1, const T& v2, const T& v3) const
     {
-      query q (table_, column_);
+      query_base q (table_, column_);
       q += "IN (";
       q.append<T, ID> (val_bind<T> (v1), conversion_);
       q += ",";
@@ -53,10 +53,10 @@ namespace odb
     }
 
     template <typename T, database_type_id ID>
-    query query_column<T, ID>::
+    query_base query_column<T, ID>::
     in (const T& v1, const T& v2, const T& v3, const T& v4) const
     {
-      query q (table_, column_);
+      query_base q (table_, column_);
       q += "IN (";
       q.append<T, ID> (val_bind<T> (v1), conversion_);
       q += ",";
@@ -70,10 +70,10 @@ namespace odb
     }
 
     template <typename T, database_type_id ID>
-    query query_column<T, ID>::
+    query_base query_column<T, ID>::
     in (const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) const
     {
-      query q (table_, column_);
+      query_base q (table_, column_);
       q += "IN (";
       q.append<T, ID> (val_bind<T> (v1), conversion_);
       q += ",";
@@ -90,10 +90,10 @@ namespace odb
 
     template <typename T, database_type_id ID>
     template <typename I>
-    query query_column<T, ID>::
+    query_base query_column<T, ID>::
     in_range (I begin, I end) const
     {
-      query q (table_, column_);
+      query_base q (table_, column_);
       q += "IN (";
 
       for (I i (begin); i != end; ++i)
@@ -103,6 +103,7 @@ namespace odb
 
         q.append<T, ID> (val_bind<T> (*i), conversion_);
       }
+
       q += ")";
       return q;
     }
diff --git a/odb/mysql/simple-object-result.hxx b/odb/mysql/simple-object-result.hxx
index b92c5ce..bcf74f7 100644
--- a/odb/mysql/simple-object-result.hxx
+++ b/odb/mysql/simple-object-result.hxx
@@ -14,7 +14,7 @@
 #include <odb/details/shared-ptr.hxx>
 
 #include <odb/mysql/version.hxx>
-#include <odb/mysql/forward.hxx> // query
+#include <odb/mysql/forward.hxx> // query_base
 #include <odb/mysql/statement.hxx>
 
 namespace odb
@@ -27,11 +27,11 @@ namespace odb
     public:
       typedef odb::object_result_impl<T> base_type;
 
-      typedef typename base_type::object_type object_type;
-      typedef typename base_type::object_traits object_traits;
       typedef typename base_type::id_type id_type;
-
+      typedef typename base_type::object_type object_type;
       typedef typename base_type::pointer_type pointer_type;
+
+      typedef object_traits_impl<object_type, id_mysql> object_traits;
       typedef typename base_type::pointer_traits pointer_traits;
 
       typedef typename object_traits::statements_type statements_type;
@@ -39,7 +39,7 @@ namespace odb
       virtual
       ~object_result_impl ();
 
-      object_result_impl (const query&,
+      object_result_impl (const query_base&,
                           details::shared_ptr<select_statement>,
                           statements_type&);
 
diff --git a/odb/mysql/simple-object-result.txx b/odb/mysql/simple-object-result.txx
index b5a5f3a..e341b16 100644
--- a/odb/mysql/simple-object-result.txx
+++ b/odb/mysql/simple-object-result.txx
@@ -23,7 +23,7 @@ namespace odb
 
     template <typename T>
     object_result_impl<T>::
-    object_result_impl (const query&,
+    object_result_impl (const query_base&,
                         details::shared_ptr<select_statement> statement,
                         statements_type& statements)
         : base_type (statements.connection ().database ()),
diff --git a/odb/mysql/simple-object-statements.hxx b/odb/mysql/simple-object-statements.hxx
index d369313..27f65a1 100644
--- a/odb/mysql/simple-object-statements.hxx
+++ b/odb/mysql/simple-object-statements.hxx
@@ -147,7 +147,7 @@ namespace odb
     struct optimistic_data<T, true>
     {
       typedef T object_type;
-      typedef odb::object_traits<object_type> object_traits;
+      typedef object_traits_impl<object_type, id_mysql> object_traits;
 
       optimistic_data (MYSQL_BIND*);
 
@@ -170,7 +170,7 @@ namespace odb
     {
     public:
       typedef T object_type;
-      typedef odb::object_traits<object_type> object_traits;
+      typedef object_traits_impl<object_type, id_mysql> object_traits;
       typedef typename object_traits::id_type id_type;
       typedef typename object_traits::pointer_type pointer_type;
       typedef typename object_traits::image_type image_type;
diff --git a/odb/mysql/statement-cache.hxx b/odb/mysql/statement-cache.hxx
index f801972..faea870 100644
--- a/odb/mysql/statement-cache.hxx
+++ b/odb/mysql/statement-cache.hxx
@@ -32,7 +32,7 @@ namespace odb
       statement_cache (connection& conn): conn_ (conn) {}
 
       template <typename T>
-      typename object_traits<T>::statements_type&
+      typename object_traits_impl<T, id_mysql>::statements_type&
       find_object ();
 
 
diff --git a/odb/mysql/statement-cache.txx b/odb/mysql/statement-cache.txx
index 3acc5fe..0517159 100644
--- a/odb/mysql/statement-cache.txx
+++ b/odb/mysql/statement-cache.txx
@@ -7,10 +7,13 @@ namespace odb
   namespace mysql
   {
     template <typename T>
-    typename object_traits<T>::statements_type& statement_cache::
+    typename object_traits_impl<T, id_mysql>::statements_type&
+    statement_cache::
     find_object ()
     {
-      typedef typename object_traits<T>::statements_type statements_type;
+      typedef
+      typename object_traits_impl<T, id_mysql>::statements_type
+      statements_type;
 
       map::iterator i (map_.find (&typeid (T)));
 
diff --git a/odb/mysql/view-result.hxx b/odb/mysql/view-result.hxx
index ab59f03..14a6002 100644
--- a/odb/mysql/view-result.hxx
+++ b/odb/mysql/view-result.hxx
@@ -14,7 +14,7 @@
 #include <odb/details/shared-ptr.hxx>
 
 #include <odb/mysql/version.hxx>
-#include <odb/mysql/forward.hxx> // query, view_statements
+#include <odb/mysql/forward.hxx> // query_base, view_statements
 #include <odb/mysql/statement.hxx>
 
 namespace odb
@@ -28,9 +28,9 @@ namespace odb
       typedef odb::view_result_impl<T> base_type;
 
       typedef typename base_type::view_type view_type;
-      typedef typename base_type::view_traits view_traits;
-
       typedef typename base_type::pointer_type pointer_type;
+
+      typedef view_traits_impl<view_type, id_mysql> view_traits;
       typedef typename base_type::pointer_traits pointer_traits;
 
       typedef view_statements<view_type> statements_type;
@@ -38,7 +38,7 @@ namespace odb
       virtual
       ~view_result_impl ();
 
-      view_result_impl (const query&,
+      view_result_impl (const query_base&,
                         details::shared_ptr<select_statement>,
                         statements_type&);
 
diff --git a/odb/mysql/view-result.txx b/odb/mysql/view-result.txx
index bc56ebb..27eb1ab 100644
--- a/odb/mysql/view-result.txx
+++ b/odb/mysql/view-result.txx
@@ -21,7 +21,7 @@ namespace odb
 
     template <typename T>
     view_result_impl<T>::
-    view_result_impl (const query&,
+    view_result_impl (const query_base&,
                       details::shared_ptr<select_statement> statement,
                       statements_type& statements)
         : base_type (statements.connection ().database ()),
diff --git a/odb/mysql/view-statements.hxx b/odb/mysql/view-statements.hxx
index 9905c51..9beb44d 100644
--- a/odb/mysql/view-statements.hxx
+++ b/odb/mysql/view-statements.hxx
@@ -26,7 +26,7 @@ namespace odb
     {
     public:
       typedef T view_type;
-      typedef odb::view_traits<view_type> view_traits;
+      typedef view_traits_impl<view_type, id_mysql> view_traits;
       typedef typename view_traits::pointer_type pointer_type;
       typedef typename view_traits::image_type image_type;
 
-- 
cgit v1.1