diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2011-03-10 08:44:28 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2011-03-21 15:39:59 +0200 |
commit | 7ae497743c7b042904fe1f6b4153ab3f4763ff2b (patch) | |
tree | 08ba3f742f20d16d893856ccceb070094bd69225 /odb/relational/common.cxx | |
parent | 2436f20262a41bd1cafa5107ab6d6799c03e0964 (diff) |
Split MySQL code generator into common and db-specific parts
The common part (in relational/) still has some MySQL-specific parts.
Also, add the notion of the current context which is used to avoid
explicitly passing the context object to every generator's c-tor.
Diffstat (limited to 'odb/relational/common.cxx')
-rw-r--r-- | odb/relational/common.cxx | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/odb/relational/common.cxx b/odb/relational/common.cxx new file mode 100644 index 0000000..0bcc676 --- /dev/null +++ b/odb/relational/common.cxx @@ -0,0 +1,178 @@ +// file : odb/relational/common.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +// license : GNU GPL v3; see accompanying LICENSE file + +#include <string> +#include <cstddef> // std::size_ +#include <cstdlib> // abort +#include <sstream> +#include <cxxabi.h> // abi::__cxa_demangle + +#include <odb/relational/common.hxx> + +using namespace std; + +namespace relational +{ + // query_columns + // + + query_columns:: + query_columns () + : ptr_ (true), decl_ (true) + { + } + + query_columns:: + query_columns (semantics::class_& cl) //@@ context::object + : ptr_ (true), decl_ (false) + { + scope_ = "access::object_traits< " + cl.fq_name () + " >::query_type"; + table_ = table_name (cl); + } + + void query_columns:: + composite (semantics::data_member& m, semantics::class_& c) + { + string name (public_name (m)); + + if (decl_) + { + os << "// " << name << endl + << "//" << endl + << "struct " << name + << "{"; + + object_columns_base::composite (m, c); + + os << "};"; + } + else + { + string old_scope (scope_); + scope_ += "::" + name; + + object_columns_base::composite (m, c); + + scope_ = old_scope; + } + } + + bool query_columns:: + column (semantics::data_member& m, string const& col_name, bool) + { + string name (public_name (m)); + + if (semantics::class_* c = object_pointer (m.type ())) + { + // We cannot just typedef the query_type from the referenced + // object for two reasons: (1) it may not be defined yet and + // (2) it will contain columns for its own pointers which + // won't work (for now we only support one level of indirection + // in queries). So we will have to duplicate the columns (sans + // the pointers). + // + if (ptr_) + { + ptr_ = false; + + if (decl_) + { + os << "// " << name << endl + << "//" << endl + << "struct " << name + << "{"; + + traverse (*c); + + os << "};"; + } + else + { + string old_scope (scope_), old_table (table_); + scope_ += "::" + name; + table_ = table_name (*c); + traverse (*c); + table_ = old_table; + scope_ = old_scope; + } + + ptr_ = true; + } + } + else + { + string im_type (image_type (m)); + string db_type (database_type (m)); + + string type ( + "mysql::value_traits< " + + m.type ().fq_name (m.belongs ().hint ()) + ", " + + im_type + ", " + + db_type + + " >::query_type"); + + if (decl_) + { + os << "// " << name << endl + << "//" << endl + << "static const mysql::query_column<" << endl + << " " << type << "," << endl + << " " << db_type << ">" << endl + << name << ";" + << endl; + } + else + { + string column ("\"`" + table_ + "`.`" + col_name + "`\""); + + os << "const mysql::query_column<" << endl + << " " << type << "," << endl + << " " << db_type << ">" << endl + << scope_ << "::" << name << " (" << endl + << column << ");" + << endl; + } + } + + return true; + } + + // + // Dynamic traversal support. + // + + struct demangled_name + { + demangled_name (): s (0), n (0) {} + ~demangled_name () {free (s);} + char* s; + size_t n; + }; + + static demangled_name name_; + + database entry_base:: + db (type_info const& ti) + { + char*& s (name_.s); + + int r; + s = abi::__cxa_demangle (ti.name (), s, &name_.n, &r); + + if (r != 0) + abort (); // We are in static initialization, so this is fatal. + + // + // + string str (s + 12); // 12 for "relational::" + istringstream is (string (str, str.find (':'))); + + database d; + if (!is >> d) + abort (); + + return d; + } +} |