From 9ad0acf37561de9bf359a561faed53de17c2ca3b Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 21 Nov 2012 13:11:43 +0200 Subject: Add dynamic multi-database query support --- odb/instance.hxx | 279 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 279 insertions(+) create mode 100644 odb/instance.hxx (limited to 'odb/instance.hxx') diff --git a/odb/instance.hxx b/odb/instance.hxx new file mode 100644 index 0000000..76e72c3 --- /dev/null +++ b/odb/instance.hxx @@ -0,0 +1,279 @@ +// file : odb/instance.hxx +// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC +// license : GNU GPL v3; see accompanying LICENSE file + +#ifndef ODB_INSTANCE_HXX +#define ODB_INSTANCE_HXX + +#include +#include +#include // std::size_t +#include + +#include +#include + +#include +#include + +// +// Dynamic traversal instantiation support. +// + +template +struct factory +{ + static B* + create (B const& prototype) + { + std::string kind, name; + database db (context::current ().options.database ()[0]); + + switch (db) + { + case database::common: + { + name = "common"; + break; + } + case database::mssql: + case database::mysql: + case database::oracle: + case database::pgsql: + case database::sqlite: + { + kind = "relational"; + name = kind + "::" + db.string (); + break; + } + } + + if (map_ != 0) + { + typename map::const_iterator i; + + if (!name.empty ()) + i = map_->find (name); + + if (i == map_->end ()) + i = map_->find (kind); + + if (i != map_->end ()) + return i->second (prototype); + } + + return new B (prototype); + } + +private: + template + friend struct entry; + + static void + init () + { + if (factory::count_++ == 0) + factory::map_ = new typename factory::map; + } + + static void + term () + { + if (--factory::count_ == 0) + delete factory::map_; + } + + typedef B* (*create_func) (B const&); + typedef std::map map; + static map* map_; + static std::size_t count_; +}; + +template +typename factory::map* factory::map_; + +template +std::size_t factory::count_; + +struct entry_base +{ + static std::string + name (std::type_info const&); +}; + +template +struct entry: entry_base +{ + typedef typename D::base base; + + entry () + { + factory::init (); + (*factory::map_)[name (typeid (D))] = &create; + } + + ~entry () + { + factory::term (); + } + + static base* + create (base const& prototype) + { + return new D (prototype); + } +}; + +template +struct instance +{ + typedef typename B::base base_type; + typedef ::factory factory_type; + + ~instance () + { + delete x_; + } + + instance () + { + base_type prototype; + x_ = factory_type::create (prototype); + } + + template + instance (A1& a1) + { + base_type prototype (a1); + x_ = factory_type::create (prototype); + } + + template + instance (A1 const& a1) + { + base_type prototype (a1); + x_ = factory_type::create (prototype); + } + + template + instance (A1& a1, A2& a2) + { + base_type prototype (a1, a2); + x_ = factory_type::create (prototype); + } + + template + instance (A1 const& a1, A2 const& a2) + { + base_type prototype (a1, a2); + x_ = factory_type::create (prototype); + } + + template + instance (A1& a1, A2& a2, A3& a3) + { + base_type prototype (a1, a2, a3); + x_ = factory_type::create (prototype); + } + + template + instance (A1 const& a1, A2 const& a2, A3 const& a3) + { + base_type prototype (a1, a2, a3); + x_ = factory_type::create (prototype); + } + + template + instance (A1& a1, A2& a2, A3& a3, A4& a4) + { + base_type prototype (a1, a2, a3, a4); + x_ = factory_type::create (prototype); + } + + template + instance (A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4) + { + base_type prototype (a1, a2, a3, a4); + x_ = factory_type::create (prototype); + } + + template + instance (A1& a1, A2& a2, A3& a3, A4& a4, A5& a5) + { + base_type prototype (a1, a2, a3, a4, a5); + x_ = factory_type::create (prototype); + } + + template + instance (A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, + A5 const& a5) + { + base_type prototype (a1, a2, a3, a4, a5); + x_ = factory_type::create (prototype); + } + + instance (instance const& i) + { + // This is tricky: use the other instance as a prototype. + // + x_ = factory_type::create (*i.x_); + } + + base_type* + operator-> () const + { + return x_; + } + + base_type& + operator* () const + { + return *x_; + } + + base_type* + get () const + { + return x_; + } + +private: + instance& operator= (instance const&); + +private: + base_type* x_; +}; + +template +inline traversal::edge_base& +operator>> (instance& n, traversal::edge_base& e) +{ + n->edge_traverser (e); + return e; +} + +template +inline traversal::relational::edge_base& +operator>> (instance& n, traversal::relational::edge_base& e) +{ + n->edge_traverser (e); + return e; +} + +template +inline traversal::node_base& +operator>> (traversal::edge_base& e, instance& n) +{ + e.node_traverser (*n); + return *n; +} + +template +inline traversal::relational::node_base& +operator>> (traversal::relational::edge_base& e, instance& n) +{ + e.node_traverser (*n); + return *n; +} + +#endif // ODB_INSTANCE_HXX -- cgit v1.1