From 8f59ca1a8d7093655f8f7d61f101abc6df3839d5 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 24 Mar 2011 12:35:08 +0200 Subject: Generalization work for MySQL and SQLite support --- odb/common.cxx | 25 ++- odb/common.hxx | 11 +- odb/context.cxx | 2 + odb/context.hxx | 1 + odb/relational/common.cxx | 8 +- odb/relational/context.cxx | 8 +- odb/relational/context.hxx | 35 ++++ odb/relational/header.cxx | 13 +- odb/relational/header.hxx | 72 +++++-- odb/relational/mysql/context.cxx | 3 + odb/relational/mysql/context.hxx | 1 - odb/relational/mysql/source.cxx | 16 +- odb/relational/source.cxx | 42 +--- odb/relational/source.hxx | 426 +++++++++++++++++++++++--------------- odb/relational/sqlite/context.cxx | 3 + odb/relational/sqlite/source.cxx | 20 +- 16 files changed, 432 insertions(+), 254 deletions(-) diff --git a/odb/common.cxx b/odb/common.cxx index 1115565..f82d3d9 100644 --- a/odb/common.cxx +++ b/odb/common.cxx @@ -149,6 +149,11 @@ traverse (semantics::data_member& m) // void object_columns_base:: +flush () +{ +} + +void object_columns_base:: composite (semantics::data_member&, semantics::class_& c) { inherits (c); @@ -178,6 +183,9 @@ traverse_composite (semantics::data_member& m, } composite (m, c); + + if (!member_.first_) + flush (); } void object_columns_base:: @@ -190,6 +198,11 @@ traverse (semantics::class_& c) if (!(obj || context::comp_value (c))) return; + bool f (top_level_); + + if (top_level_) + top_level_ = false; + semantics::class_* prev; if (obj) { @@ -202,6 +215,9 @@ traverse (semantics::class_& c) if (obj) object = prev; + + if (f && !member_.first_) + flush (); } void object_columns_base::member:: @@ -243,9 +259,10 @@ traverse (semantics::data_member& m) } else { - oc_.column (m, prefix_ + column_name (m), first_); - - if (first_) - first_ = false; + if (oc_.column (m, prefix_ + column_name (m), first_)) + { + if (first_) + first_ = false; + } } } diff --git a/odb/common.hxx b/odb/common.hxx index 8bf7b8e..f0c2d5a 100644 --- a/odb/common.hxx +++ b/odb/common.hxx @@ -110,15 +110,22 @@ struct object_columns_base: traversal::class_, virtual context virtual void composite (semantics::data_member&, semantics::class_&); + // Called after the last column, provided at least one column hasn't + // been ignored. + // + virtual void + flush (); + public: object_columns_base () - : member_ (*this) + : top_level_ (true), member_ (*this) { init (); } object_columns_base (object_columns_base const&) : context (), //@@ -Wextra + top_level_ (true), member_ (*this) { init (); @@ -159,6 +166,8 @@ private: bool first_; }; + bool top_level_; + member member_; traversal::names names_; traversal::inherits inherits_; diff --git a/odb/context.cxx b/odb/context.cxx index 090b13c..e2096d9 100644 --- a/odb/context.cxx +++ b/odb/context.cxx @@ -109,6 +109,7 @@ context (ostream& os_, os (data_->os_), unit (u), options (ops), + db (options.database ()), keyword_set (data_->keyword_set_), embedded_schema (ops.generate_schema () && ops.schema_format ().count (schema_format::embedded)), @@ -127,6 +128,7 @@ context () os (current ().os), unit (current ().unit), options (current ().options), + db (current ().db), keyword_set (current ().keyword_set), embedded_schema (current ().embedded_schema), object (current ().object) diff --git a/odb/context.hxx b/odb/context.hxx index 0de95c1..ef8b2c8 100644 --- a/odb/context.hxx +++ b/odb/context.hxx @@ -339,6 +339,7 @@ public: std::ostream& os; semantics::unit& unit; options_type const& options; + database const db; typedef std::set keyword_set_type; keyword_set_type const& keyword_set; diff --git a/odb/relational/common.cxx b/odb/relational/common.cxx index 7ac2fc1..1416305 100644 --- a/odb/relational/common.cxx +++ b/odb/relational/common.cxx @@ -29,7 +29,7 @@ namespace relational : ptr_ (true), decl_ (false) { scope_ = "access::object_traits< " + cl.fq_name () + " >::query_type"; - table_ = table_name (cl); + table_ = table_qname (cl); } void query_columns:: @@ -92,7 +92,7 @@ namespace relational { string old_scope (scope_), old_table (table_); scope_ += "::" + name; - table_ = table_name (*c); + table_ = table_qname (*c); traverse (*c); table_ = old_table; scope_ = old_scope; @@ -125,13 +125,13 @@ namespace relational } else { - string column ("\"`" + table_ + "`.`" + col_name + "`\""); + string column (table_ + '.' + quote_id (col_name)); os << "const mysql::query_column<" << endl << " " << type << "," << endl << " " << db_type_id << ">" << endl << scope_ << "::" << name << " (" << endl - << column << ");" + << strlit (column) << ");" << endl; } } diff --git a/odb/relational/context.cxx b/odb/relational/context.cxx index f763b8d..fcf3ac2 100644 --- a/odb/relational/context.cxx +++ b/odb/relational/context.cxx @@ -22,13 +22,17 @@ namespace relational context:: context () - : data_ (current ().data_) + : data_ (current ().data_), + bind_vector (data_->bind_vector_), + truncated_vector (data_->truncated_vector_) { } context:: context (data* d) - : data_ (d) + : data_ (d), + bind_vector (data_->bind_vector_), + truncated_vector (data_->truncated_vector_) { assert (current_ == 0); current_ = this; diff --git a/odb/relational/context.hxx b/odb/relational/context.hxx index c99b400..08f8b81 100644 --- a/odb/relational/context.hxx +++ b/odb/relational/context.hxx @@ -33,6 +33,34 @@ namespace relational string quote_id (string const&) const; + // Quoted column and table names. + // + string + column_qname (semantics::data_member& m) const + { + return quote_id (column_name (m)); + } + + string + column_qname (semantics::data_member& m, + string const& key_prefix, + string const& default_name) const + { + return quote_id (column_name (m, key_prefix, default_name)); + } + + string + table_qname (semantics::class_& c) const + { + return quote_id (table_name (c)); + } + + string + table_qname (semantics::data_member& m, table_prefix const& p) const + { + return quote_id (table_name (m, p)); + } + protected: // The default implementation returns false. // @@ -76,8 +104,15 @@ namespace relational struct data: root_context::data { data (std::ostream& os): root_context::data (os) {} + + string bind_vector_; + string truncated_vector_; }; data* data_; + + public: + string const& bind_vector; + string const& truncated_vector; }; } diff --git a/odb/relational/header.cxx b/odb/relational/header.cxx index f8529f4..c70ef27 100644 --- a/odb/relational/header.cxx +++ b/odb/relational/header.cxx @@ -17,7 +17,6 @@ namespace relational { context ctx; ostream& os (ctx.os); - options const& ops (ctx.options); traversal::unit unit; traversal::defines unit_defines; @@ -32,16 +31,8 @@ namespace relational ns >> ns_defines >> ns; ns_defines >> c; - os << "#include " << endl - << "#include " << endl - << "#include " << endl; - - if (ops.generate_query ()) - os << "#include " << endl; - - os << endl - << "#include " << endl - << endl; + instance i; + i->generate (); os << "namespace odb" << "{"; diff --git a/odb/relational/header.hxx b/odb/relational/header.hxx index 9394f21..662e3cb 100644 --- a/odb/relational/header.hxx +++ b/odb/relational/header.hxx @@ -171,7 +171,10 @@ namespace relational if (ordered) { data_columns++; - cond_columns++; + + // Index is not currently used (see also bind()). + // + // cond_columns++; } break; } @@ -188,18 +191,24 @@ namespace relational n = 1; data_columns += n; - cond_columns += n; + + // Key is not currently used (see also bind()). + // + // cond_columns += n; + break; } case ck_set: case ck_multiset: { + // Not currently used (see also bind()) + // // Value is also a key. // - if (class_* vc = comp_value (vt)) - cond_columns += in_column_count (*vc); - else - cond_columns++; + //if (class_* vc = comp_value (vt)) + // cond_columns += in_column_count (*vc); + //else + // cond_columns++; break; } @@ -279,7 +288,7 @@ namespace relational } } - os << "typedef mysql::container_statements< " << name << + os << "typedef " << db << "::container_statements< " << name << " > statements_type;" << endl; @@ -389,19 +398,19 @@ namespace relational // bind (cond_image) // os << "static void" << endl - << "bind (MYSQL_BIND*, id_image_type*, cond_image_type&);" + << "bind (" << bind_vector << ", id_image_type*, cond_image_type&);" << endl; // bind (data_image) // os << "static void" << endl - << "bind (MYSQL_BIND*, id_image_type*, data_image_type&);" + << "bind (" << bind_vector << ", id_image_type*, data_image_type&);" << endl; // grow () // os << "static void" << endl - << "grow (data_image_type&, my_bool*);" + << "grow (data_image_type&, " << truncated_vector << ");" << endl; // init (data_image) @@ -642,7 +651,7 @@ namespace relational { // query_base_type // - os << "typedef mysql::query query_base_type;" + os << "typedef " << db << "::query query_base_type;" << endl; // query_type @@ -715,19 +724,19 @@ namespace relational // grow () // os << "static void" << endl - << "grow (image_type&, my_bool*);" + << "grow (image_type&, " << truncated_vector << ");" << endl; // bind (image_type) // os << "static void" << endl - << "bind (MYSQL_BIND*, image_type&, bool);" + << "bind (" << bind_vector << ", image_type&, bool);" << endl; // bind (id_image_type) // os << "static void" << endl - << "bind (MYSQL_BIND*, id_image_type&);" + << "bind (" << bind_vector << ", id_image_type&);" << endl; // init (image, object) @@ -802,7 +811,8 @@ namespace relational // Load the object image. // os << "static bool" << endl - << "find_ (mysql::object_statements< object_type >&, const id_type&);" + << "find_ (" << db << "::object_statements< object_type >&, " << + "const id_type&);" << endl; // Load the rest of the object (containers, etc). Expects the id @@ -810,15 +820,16 @@ namespace relational // id. // os << "static void" << endl - << "load_ (mysql::object_statements< object_type >&, object_type&);" + << "load_ (" << db << "::object_statements< object_type >&, " << + "object_type&);" << endl; if (options.generate_query ()) os << "static void" << endl << "query_ (database&," << endl << "const query_type&," << endl - << "mysql::object_statements< object_type >&," << endl - << "details::shared_ptr< mysql::select_statement >&);" + << db << "::object_statements< object_type >&," << endl + << "details::shared_ptr< " << db << "::select_statement >&);" << endl; os << "};"; @@ -849,13 +860,13 @@ namespace relational // grow () // os << "static bool" << endl - << "grow (image_type&, my_bool*);" + << "grow (image_type&, " << truncated_vector << ");" << endl; // bind (image_type) // os << "static void" << endl - << "bind (MYSQL_BIND*, image_type&);" + << "bind (" << bind_vector << ", image_type&);" << endl; // init (image, object) @@ -877,6 +888,27 @@ namespace relational instance image_type_; instance id_image_member_; }; + + struct include: virtual context + { + typedef include base; + + virtual void + generate () + { + os << "#include " << endl + << endl; + + os << "#include " << endl + << "#include " << endl + << "#include " << endl; + + if (options.generate_query ()) + os << "#include " << endl; + + os << endl; + } + }; } } diff --git a/odb/relational/mysql/context.cxx b/odb/relational/mysql/context.cxx index 660f616..11b5290 100644 --- a/odb/relational/mysql/context.cxx +++ b/odb/relational/mysql/context.cxx @@ -72,6 +72,9 @@ namespace relational assert (current_ == 0); current_ = this; + data_->bind_vector_ = "MYSQL_BIND*"; + data_->truncated_vector_ = "my_bool*"; + // Populate the C++ type to DB type map. // for (size_t i (0); i < sizeof (type_map) / sizeof (type_map_entry); ++i) diff --git a/odb/relational/mysql/context.hxx b/odb/relational/mysql/context.hxx index 60d2905..392ec77 100644 --- a/odb/relational/mysql/context.hxx +++ b/odb/relational/mysql/context.hxx @@ -115,7 +115,6 @@ namespace relational { data (std::ostream& os): base_context::data (os) {} }; - data* data_; }; } diff --git a/odb/relational/mysql/source.cxx b/odb/relational/mysql/source.cxx index a205650..cf26082 100644 --- a/odb/relational/mysql/source.cxx +++ b/odb/relational/mysql/source.cxx @@ -265,7 +265,7 @@ namespace relational return false; ostringstream ostr; - ostr << "e[" << index_ << "UL]"; + ostr << "t[" << index_ << "UL]"; e = ostr.str (); if (var_override_.empty ()) @@ -289,7 +289,7 @@ namespace relational { os << "if (composite_value_traits< " << mi.fq_type () << " >::grow (" << endl - << "i." << mi.var << "value, e + " << index_ << "UL))" + << "i." << mi.var << "value, t + " << index_ << "UL))" << "{" << "grew = true;" << "}"; @@ -894,6 +894,18 @@ namespace relational member_database_type_id member_database_type_id_; }; entry init_value_member_; + + struct class_: relational::class_, context + { + class_ (base const& x): base (x) {} + + virtual void + init_auto_id (semantics::data_member&, string const& im) + { + os << im << "value = 0;"; + } + }; + entry class_entry_; } } } diff --git a/odb/relational/source.cxx b/odb/relational/source.cxx index be9da93..8384d96 100644 --- a/odb/relational/source.cxx +++ b/odb/relational/source.cxx @@ -17,12 +17,11 @@ namespace relational { context ctx; ostream& os (ctx.os); - options const& ops (ctx.options); traversal::unit unit; traversal::defines unit_defines; traversal::namespace_ ns; - class_ c; + instance c; unit >> unit_defines >> ns; unit_defines >> c; @@ -32,44 +31,11 @@ namespace relational ns >> ns_defines >> ns; ns_defines >> c; - // - // - os << "#include " << endl; - - if (ctx.embedded_schema) - os << "#include " << endl; - - os << endl; - - // - // - os << "#include " << endl - << "#include " << endl - << "#include " << endl - << "#include " << endl - << "#include " << endl - << "#include " << endl - << "#include " << endl - << "#include " << endl - << "#include " << endl - << "#include " << endl; - - if (ops.generate_query ()) - os << "#include " << endl; - - os << endl; - - // Details includes. - // - os << "#include " << endl; - - if (ops.generate_query ()) - os << "#include " << endl; - - os << endl; + instance i; + i->generate (); os << "namespace odb" - << "{"; + << "{"; unit.dispatch (ctx.unit); diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx index 106bf27..3bb238a 100644 --- a/odb/relational/source.hxx +++ b/odb/relational/source.hxx @@ -58,24 +58,17 @@ namespace relational { typedef object_columns base; - object_columns (std::string const& table_name, - bool out, + object_columns (bool out, + bool last = true, char const* suffix = "") - : table_name_ (table_name), - out_ (out), - first_ (true), - suffix_ (suffix) + : out_ (out), last_ (last), suffix_ (suffix) { } - object_columns (std::string const& table_name, + object_columns (std::string const& table_qname, bool out, - bool first, - char const* suffix = "") - : table_name_ (table_name), - out_ (out), - first_ (first), - suffix_ (suffix) + bool last = true) + : table_name_ (table_qname), out_ (out), last_ (last) { } @@ -89,8 +82,13 @@ namespace relational if (im != 0 && !out_) return false; - if (!first || !first_) - os << ",\"" << endl; + if (!first) + { + line_ += ','; + os << strlit (line_) << endl; + } + + line_.clear (); // Inverse object pointers come from a joined table. // @@ -103,29 +101,58 @@ namespace relational // This container is a direct member of the class so the table // prefix is just the class table name. // - table_prefix tp (table_name (*c) + "_", 1); - string const& it (table_name (*im, tp)); - string const& id (column_name (*im, "id", "object_id")); + if (!table_name_.empty ()) + { + table_prefix tp (table_name (*c) + "_", 1); + string const& it (table_qname (*im, tp)); - os << "\"`" << it << "`.`" << id << "`" << suffix_; + line_ += it; + line_ += '.'; + } + + line_ += column_qname (*im, "id", "object_id"); } else { - os << "\"`" << table_name (*c) << "`.`" << - column_name (id_member (*c)) << "`" << suffix_; + if (!table_name_.empty ()) + { + line_ += table_qname (*c); + line_ += '.'; + } + + line_ += column_qname (id_member (*c)); } } else - os << "\"`" << table_name_ << "`.`" << name << "`" << suffix_; + { + if (!table_name_.empty ()) + { + line_ += table_name_; + line_ += '.'; + } + line_ += quote_id (name); + } + + line_ += suffix_; return true; } + virtual void + flush () + { + if (!last_) + line_ += ','; + + os << strlit (line_) << endl; + } + private: string table_name_; bool out_; - bool first_; + bool last_; string suffix_; + string line_; }; struct object_joins: object_columns_base, virtual context @@ -136,7 +163,7 @@ namespace relational // object_joins (semantics::class_& scope, bool query) : query_ (query), - table_ (table_name (scope)), + table_ (table_qname (scope)), id_ (id_member (scope)) { } @@ -155,18 +182,20 @@ namespace relational if (i->table.empty ()) continue; - os << "\" LEFT JOIN `" << i->table << "` ON "; + string line (" LEFT JOIN "); + line += i->table; + line += " ON "; for (conditions::iterator b (i->cond.begin ()), j (b); j != i->cond.end (); ++j) { if (j != b) - os << " OR "; + line += " OR "; - os << *j; + line += *j; } - os << "\"" << endl; + os << strlit (line) << endl; } } @@ -190,11 +219,11 @@ namespace relational // string const& ct (table_name (*c)); table_prefix tp (ct + "_", 1); - t = table_name (*im, tp); - string const& val (column_name (*im, "value", "value")); + t = table_qname (*im, tp); + string const& val (column_qname (*im, "value", "value")); - cond << "`" << t << "`.`" << val << "` = `" << - table_ << "`.`" << column_name (id_) << "`"; + cond << t << '.' << val << " = " << table_ << '.' << + column_qname (id_); // Add the join for the object itself so that we are able to // use it in the WHERE clause. @@ -202,18 +231,18 @@ namespace relational if (query_) { dt = ct; - string const& id (column_name (*im, "id", "object_id")); + string const& id (column_qname (*im, "id", "object_id")); - dcond << "`" << dt << "`.`" << column_name (id_member (*c)) << - "` = `" << t << "`.`" << id << "`"; + dcond << dt << '.' << column_qname (id_member (*c)) << " = " << + t << '.' << id; } } else { - t = table_name (*c); + t = table_qname (*c); - cond << "`" << t << "`.`" << column_name (*im) << "` = `" << - table_ << "`.`" << column_name (id_) << "`"; + cond << t << '.' << column_qname (*im) << " = " << + table_ << '.' << column_qname (id_); } } else if (query_) @@ -221,10 +250,10 @@ namespace relational // We need the join to be able to use the referenced object // in the WHERE clause. // - t = table_name (*c); + t = table_qname (*c); - cond << "`" << t << "`.`" << column_name (id_member (*c)) << - "` = `" << table_ << "`.`" << col_name << "`"; + cond << t << '.' << column_qname (id_member (*c)) << " = " << + table_ << '.' << quote_id (col_name); } if (!t.empty ()) @@ -394,7 +423,7 @@ namespace relational os << "// " << c.name () << " base" << endl << "//" << endl << "if (composite_value_traits< " << c.fq_name () << - " >::grow (i, e + " << index_ << "UL))" + " >::grow (i, t + " << index_ << "UL))" << "{" << "grew = true;" << "}"; @@ -578,7 +607,7 @@ namespace relational // // Statements. // - string table (table_name (m, table_prefix_)); + string table (table_qname (m, table_prefix_)); // select_all_statement // @@ -602,29 +631,31 @@ namespace relational // table prefix is just the class table name. // table_prefix tp (table_name (*c) + "_", 1); - inv_table = table_name (*im, tp); - inv_id = column_name (*im, "id", "object_id"); - inv_fid = column_name (*im, "value", "value"); + inv_table = table_qname (*im, tp); + inv_id = column_qname (*im, "id", "object_id"); + inv_fid = column_qname (*im, "value", "value"); } else { // many(i)-to-one // - inv_table = table_name (*c); - inv_id = column_name (id_member (*c)); - inv_fid = column_name (*im); + inv_table = table_qname (*c); + inv_id = column_qname (id_member (*c)); + inv_fid = column_qname (*im); } - os << "\"SELECT \"" << endl - << "\"`" << inv_fid << "`,\"" << endl - << "\"`" << inv_id << "`\"" << endl - << "\" FROM `" << inv_table << "` WHERE `" << - inv_fid << "` = ?\""; + os << strlit ("SELECT ") << endl + << strlit (inv_table + '.' + inv_fid + ',') << endl + << strlit (inv_table + '.' + inv_id) << endl + << strlit (" FROM " + inv_table + + " WHERE " + inv_table + '.' + inv_fid + " = ?"); } else { - os << "\"SELECT \"" << endl - << "\"`" << column_name (m, "id", "object_id") << "`"; + string const& id_col (column_qname (m, "id", "object_id")); + + os << strlit ("SELECT ") << endl + << strlit (table + '.' + id_col + ',') << endl; switch (ck) { @@ -632,8 +663,8 @@ namespace relational { if (ordered) { - os << ",\"" << endl - << "\"`" << column_name (m, "index", "index") << "`"; + string const& col (column_qname (m, "index", "index")); + os << strlit (table + '.' + col + ',') << endl; } break; } @@ -647,8 +678,8 @@ namespace relational } else { - os << ",\"" << endl - << "\"`" << column_name (m, "key", "key") << "`"; + string const& col (column_qname (m, "key", "key")); + os << strlit (table + '.' + col + ',') << endl; } break; } @@ -661,22 +692,23 @@ namespace relational if (semantics::class_* cvt = comp_value (vt)) { - instance t (table, false, false); + instance t (table, false); t->traverse_composite (m, *cvt, "value", "value"); } else { - os << ",\"" << endl - << "\"`" << column_name (m, "value", "value") << "`"; + string const& col (column_qname (m, "value", "value")); + os << strlit (table + '.' + col) << endl; } - os << "\"" << endl - << "\" FROM `" << table << "` WHERE `" << - column_name (m, "id", "object_id") << "` = ?\"" << endl; + os << strlit (" FROM " + table + + " WHERE " + table + '.' + id_col + " = ?") << endl; if (ordered) - os << "\" ORDER BY `" << column_name (m, "index", "index") << - "`\""; + { + string const& col (column_qname (m, "index", "index")); + os << strlit (" ORDER BY " + table + '.' + col) << endl; + } } os << ";" @@ -688,22 +720,20 @@ namespace relational "::insert_one_statement =" << endl; if (inverse) - os << " \"\";" + os << strlit ("") << ";" << endl; else { - os << "\"INSERT INTO `" << table << "` (\"" << endl - << "\"`" << column_name (m, "id", "object_id") << "`"; + os << strlit ("INSERT INTO " + table + " (") << endl + << strlit (column_qname (m, "id", "object_id") + ',') << endl; switch (ck) { case ck_ordered: { if (ordered) - { - os << ",\"" << endl - << "\"`" << column_name (m, "index", "index") << "`"; - } + os << strlit (column_qname (m, "index", "index") + ',') << + endl; break; } case ck_map: @@ -711,14 +741,11 @@ namespace relational { if (semantics::class_* ckt = comp_value (*kt)) { - instance t (table, false, false); + instance t (false, false); t->traverse_composite (m, *ckt, "key", "key"); } else - { - os << ",\"" << endl - << "\"`" << column_name (m, "key", "key") << "`"; - } + os << strlit (column_qname (m, "key", "key") + ',') << endl; break; } case ck_set: @@ -730,22 +757,18 @@ namespace relational if (semantics::class_* cvt = comp_value (vt)) { - instance t (table, false, false); + instance t (false); t->traverse_composite (m, *cvt, "value", "value"); } else - { - os << ",\"" << endl - << "\"`" << column_name (m, "value", "value") << "`"; - } + os << strlit (column_qname (m, "value", "value")) << endl; - os << "\"" << endl - << "\") VALUES ("; + string values; + for (size_t i (0), n (m.get ("data-column-count")); + i < n; ++i) + values += i != 0 ? ",?" : "?"; - for (size_t i (0), n (m.get ("data-column-count")); i < n; ++i) - os << (i != 0 ? "," : "") << '?'; - - os << ")\";" + os << strlit (") VALUES (" + values + ")") << ";" << endl; } @@ -755,12 +778,13 @@ namespace relational "::delete_all_statement =" << endl; if (inverse) - os << " \"\";" + os << strlit ("") << ";" << endl; else { - os << "\"DELETE FROM `" << table << "`\"" << endl - << "\" WHERE `" << column_name (m, "id", "object_id") << "` = ?\";" + os << strlit ("DELETE FROM " + table) << endl + << strlit (" WHERE " + column_qname (m, "id", "object_id") + + " = ?") << ";" << endl; } @@ -776,7 +800,8 @@ namespace relational // bind (cond_image_type) // os << "void " << scope << "::" << endl - << "bind (MYSQL_BIND* b, id_image_type* p, cond_image_type& c)" + << "bind (" << bind_vector << " b, id_image_type* p, " << + "cond_image_type& c)" << "{" << "ODB_POTENTIALLY_UNUSED (c);" << endl @@ -796,6 +821,9 @@ namespace relational // We don't need to update the bind index since this is the // last element. // + // Index/key is currently not used (see also cond_column_count). + // +#if 0 switch (ck) { case ck_ordered: @@ -830,13 +858,15 @@ namespace relational break; } } +#endif os << "}"; // bind (data_image_type) // os << "void " << scope << "::" << endl - << "bind (MYSQL_BIND* b, id_image_type* p, data_image_type& d)" + << "bind (" << bind_vector << " b, id_image_type* p, " << + "data_image_type& d)" << "{" << "size_t n (0);" << endl; @@ -907,7 +937,7 @@ namespace relational size_t index (0); os << "void " << scope << "::" << endl - << "grow (data_image_type& i, my_bool* e)" + << "grow (data_image_type& i, " << truncated_vector << " t)" << "{" << "bool grew (false);" << endl; @@ -1143,7 +1173,7 @@ namespace relational if (!inverse) { - os << "using namespace mysql;" + os << "using namespace " << db << ";" << endl << "typedef container_statements< " << name << " > statements;" << "statements& sts (*static_cast< statements* > (d));" @@ -1215,7 +1245,7 @@ namespace relational } os << "{" - << "using namespace mysql;" + << "using namespace " << db << ";" << endl << "typedef container_statements< " << name << " > statements;" << "statements& sts (*static_cast< statements* > (d));" @@ -1276,7 +1306,7 @@ namespace relational os << endl << "if (r == select_statement::truncated)" << "{" - << "grow (di, sts.data_image_error ());" + << "grow (di, sts.data_image_truncated ());" << endl << "if (di.version != sts.data_image_version ())" << "{" @@ -1303,7 +1333,7 @@ namespace relational << "{"; if (!inverse) - os << "using namespace mysql;" + os << "using namespace " << db << ";" << endl << "typedef container_statements< " << name << " > statements;" << "statements& sts (*static_cast< statements* > (d));" @@ -1320,7 +1350,7 @@ namespace relational << "id_image_type& id," << endl << "statements_type& sts)" << "{" - << "using namespace mysql;" + << "using namespace " << db << ";" << endl << "binding& b (sts.data_image_binding ());" << "if (id.version != sts.data_id_image_version () || " << @@ -1347,7 +1377,7 @@ namespace relational << "id_image_type& id," << endl << "statements_type& sts)" << "{" - << "using namespace mysql;" + << "using namespace " << db << ";" << endl << "binding& db (sts.data_image_binding ());" << "if (id.version != sts.data_id_image_version () || db.version == 0)" @@ -1379,7 +1409,7 @@ namespace relational << "if (r == select_statement::truncated)" << "{" << "data_image_type& di (sts.data_image ());" - << "grow (di, sts.data_image_error ());" + << "grow (di, sts.data_image_truncated ());" << endl << "if (di.version != sts.data_image_version ())" << "{" @@ -1413,7 +1443,7 @@ namespace relational << "id_image_type& id," << endl << "statements_type& sts)" << "{" - << "using namespace mysql;" + << "using namespace " << db << ";" << endl << "binding& db (sts.data_image_binding ());" << "if (id.version != sts.data_id_image_version () || " << @@ -1451,7 +1481,7 @@ namespace relational os << "void " << scope << "::" << endl << "erase (id_image_type& id, statements_type& sts)" << "{" - << "using namespace mysql;" + << "using namespace " << db << ";" << endl << "binding& b (sts.cond_image_binding ());" << "if (id.version != sts.cond_id_image_version () || b.version == 0)" @@ -1492,7 +1522,7 @@ namespace relational container (semantics::data_member& m) { string traits (prefix_ + public_name (m) + "_traits"); - os << "mysql::container_statements< " << traits << " > " << + os << db << "::container_statements< " << traits << " > " << prefix_ << m.name () << ";"; } }; @@ -1663,6 +1693,12 @@ namespace relational init_value_member_names_ >> init_value_member_; } + virtual void + init_auto_id (semantics::data_member&, // id member + string const&) // image variable prefix + { + assert (false); + } virtual void traverse (type& c) @@ -1708,7 +1744,7 @@ namespace relational cm->traverse (c); os << (containers ? "\n" : "") - << "container_statement_cache_type (mysql::connection&" << + << "container_statement_cache_type (" << db << "::connection&" << (containers ? " c" : "") << ")"; instance im; @@ -1735,39 +1771,37 @@ namespace relational t->traverse (c); } - string const& table (table_name (c)); + string const& table (table_qname (c)); + string const& id_col (column_qname (id)); // persist_statement // os << "const char* const " << traits << "::persist_statement =" << endl - << "\"INSERT INTO `" << table << "` (\"" << endl; + << strlit ("INSERT INTO " + table + " (") << endl; { - instance t (table, false); + instance t (false); t->traverse (c); } - os << "\"" << endl - << "\") VALUES ("; - + string values; for (size_t i (0), n (in_column_count (c)); i < n; ++i) - os << (i != 0 ? "," : "") << '?'; + values += i != 0 ? ",?" : "?"; - os << ")\";" + os << strlit (") VALUES (" + values + ")") << ";" << endl; // find_statement // os << "const char* const " << traits << "::find_statement =" << endl - << "\"SELECT \"" << endl; + << strlit ("SELECT ") << endl; { instance t (table, true); t->traverse (c); } - os << "\"" << endl - << "\" FROM `" << table << "`\"" << endl; + os << strlit (" FROM " + table) << endl; { bool f (false); @@ -1776,28 +1810,27 @@ namespace relational t->write (); } - os << "\" WHERE `" << table << "`.`" << column_name (id) << "` = ?\";" + os << strlit (" WHERE " + table + '.' + id_col + " = ?") << ";" << endl; // update_statement // os << "const char* const " << traits << "::update_statement =" << endl - << "\"UPDATE `" << table << "` SET \"" << endl; + << strlit ("UPDATE " + table + " SET ") << endl; { - instance t (table, false, " = ?"); + instance t (false, true, " = ?"); t->traverse (c); } - os << "\"" << endl - << "\" WHERE `" << table << "`.`" << column_name (id) << "` = ?\";" + os << strlit (" WHERE " + table + '.' + id_col + " = ?") << ";" << endl; // erase_statement // os << "const char* const " << traits << "::erase_statement =" << endl - << "\"DELETE FROM `" << table << "`\"" << endl - << "\" WHERE `" << table << "`.`" << column_name (id) << "` = ?\";" + << strlit ("DELETE FROM " + table) << endl + << strlit (" WHERE " + table + '.' + id_col + " = ?") << ";" << endl; // query_clause @@ -1812,20 +1845,16 @@ namespace relational // and can optimize it out otherwise. // os << "const char* const " << traits << "::query_clause =" << endl - << "\"SELECT " << (oj->count () ? "DISTINCT " : "") << "\"" - << endl; + << strlit (oj->count () ? "SELECT DISTINCT " : "SELECT ") << endl; { instance oc (table, true); oc->traverse (c); } - os << "\"" << endl - << "\" FROM `" << table << "`\"" << endl; - + os << strlit (" FROM " + table) << endl; oj->write (); - - os << "\" \";" + os << strlit (" ") << ";" << endl; } @@ -1846,7 +1875,7 @@ namespace relational // grow () // os << "void " << traits << "::" << endl - << "grow (image_type& i, my_bool* e)" + << "grow (image_type& i, " << truncated_vector << " t)" << "{" << "bool grew (false);" << endl; @@ -1862,7 +1891,7 @@ namespace relational // bind (image_type) // os << "void " << traits << "::" << endl - << "bind (MYSQL_BIND* b, image_type& i, bool out)" + << "bind (" << bind_vector << " b, image_type& i, bool out)" << "{" << "ODB_POTENTIALLY_UNUSED (out);" << endl @@ -1877,7 +1906,7 @@ namespace relational // bind (id_image_type) // os << "void " << traits << "::" << endl - << "bind (MYSQL_BIND* b, id_image_type& i)" + << "bind (" << bind_vector << " b, id_image_type& i)" << "{" << "std::size_t n (0);"; bind_id_member_->traverse (id); @@ -1935,20 +1964,25 @@ namespace relational << "persist (database&, " << (auto_id ? "" : "const ") << "object_type& obj)" << "{" - << "using namespace mysql;" + << "using namespace " << db << ";" << endl - << "connection& conn (mysql::transaction::current ().connection ());" + << "connection& conn (" << db << + "::transaction::current ().connection ());" << "object_statements< object_type >& sts (" << endl << "conn.statement_cache ().find ());" << "image_type& im (sts.image ());" << "binding& imb (sts.in_image_binding ());" - << endl; + << endl + << "init (im, obj);"; if (auto_id) - os << "obj." << id.name () << " = 0;"; + { + string const& n (id.name ()); + string var ("im." + n + (n[n.size () - 1] == '_' ? "" : "_")); + init_auto_id (id, var); + } - os << "init (im, obj);" - << endl + os << endl << "if (im.version != sts.in_image_version () || imb.version == 0)" << "{" << "bind (imb.bind, im, false);" @@ -1983,9 +2017,10 @@ namespace relational os << "void " << traits << "::" << endl << "update (database&, const object_type& obj)" << "{" - << "using namespace mysql;" + << "using namespace " << db << ";" << endl - << "connection& conn (mysql::transaction::current ().connection ());" + << "connection& conn (" << db << + "::transaction::current ().connection ());" << "object_statements< object_type >& sts (" << endl << "conn.statement_cache ().find ());" << endl; @@ -2032,9 +2067,10 @@ namespace relational os << "void " << traits << "::" << endl << "erase (database&, const id_type& id)" << "{" - << "using namespace mysql;" + << "using namespace " << db << ";" << endl - << "connection& conn (mysql::transaction::current ().connection ());" + << "connection& conn (" << db << + "::transaction::current ().connection ());" << "object_statements< object_type >& sts (" << endl << "conn.statement_cache ().find ());" << endl; @@ -2072,9 +2108,10 @@ namespace relational << traits << "::" << endl << "find (database& db, const id_type& id)" << "{" - << "using namespace mysql;" + << "using namespace " << db << ";" << endl - << "connection& conn (mysql::transaction::current ().connection ());" + << "connection& conn (" << db << + "::transaction::current ().connection ());" << "object_statements< object_type >& sts (" << endl << "conn.statement_cache ().find ());" << "object_statements< object_type >::auto_lock l (sts);" @@ -2111,9 +2148,10 @@ namespace relational os << "bool " << traits << "::" << endl << "find (database& db, const id_type& id, object_type& obj)" << "{" - << "using namespace mysql;" + << "using namespace " << db << ";" << endl - << "connection& conn (mysql::transaction::current ().connection ());" + << "connection& conn (" << db << + "::transaction::current ().connection ());" << "object_statements< object_type >& sts (" << endl << "conn.statement_cache ().find ());" << "object_statements< object_type >::auto_lock l (sts);" @@ -2144,10 +2182,10 @@ namespace relational // // os << "bool " << traits << "::" << endl - << "find_ (mysql::object_statements< object_type >& sts, " << + << "find_ (" << db << "::object_statements< object_type >& sts, " << "const id_type& id)" << "{" - << "using namespace mysql;" + << "using namespace " << db << ";" << endl; // Initialize id image. @@ -2183,7 +2221,7 @@ namespace relational os << endl << "if (r == select_statement::truncated)" << "{" - << "grow (im, sts.out_image_error ());" + << "grow (im, sts.out_image_truncated ());" << endl << "if (im.version != sts.out_image_version ())" << "{" @@ -2203,8 +2241,8 @@ namespace relational if (containers) { os << "void " << traits << "::" << endl - << "load_ (mysql::object_statements< object_type >& sts, " << - "object_type& obj)" + << "load_ (" << db << "::object_statements< object_type >& " << + "sts, object_type& obj)" << "{" << "id_image_type& i (sts.id_image ());" << endl; @@ -2224,9 +2262,10 @@ namespace relational << "database& db," << endl << "const query_type& q)" << "{" - << "using namespace mysql;" + << "using namespace " << db << ";" << endl - << "connection& conn (mysql::transaction::current ().connection ());" + << "connection& conn (" << db << + "::transaction::current ().connection ());" << endl << "object_statements< object_type >& sts (" << endl << "conn.statement_cache ().find ());" @@ -2235,7 +2274,8 @@ namespace relational << "query_ (db, q, sts, st);" << endl << "details::shared_ptr > r (" << endl - << "new (details::shared) mysql::result_impl (st, sts));" + << "new (details::shared) " << db << + "::result_impl (st, sts));" << "return result (r);" << "}"; @@ -2246,9 +2286,10 @@ namespace relational << "database& db," << endl << "const query_type& q)" << "{" - << "using namespace mysql;" + << "using namespace " << db << ";" << endl - << "connection& conn (mysql::transaction::current ().connection ());" + << "connection& conn (" << db << + "::transaction::current ().connection ());" << endl << "object_statements< object_type >& sts (" << endl << "conn.statement_cache ().find ());" @@ -2257,17 +2298,18 @@ namespace relational << "query_ (db, q, sts, st);" << endl << "details::shared_ptr > r (" << endl - << "new (details::shared) mysql::result_impl (st, sts));" + << "new (details::shared) " << db << + "::result_impl (st, sts));" << "return result (r);" << "}"; os << "void " << traits << "::" << endl << "query_ (database&," << endl << "const query_type& q," << endl - << "mysql::object_statements< object_type >& sts," - << "details::shared_ptr& st)" + << db << "::object_statements< object_type >& sts," + << "details::shared_ptr<" << db << "::select_statement>& st)" << "{" - << "using namespace mysql;" + << "using namespace " << db << ";" << endl << "image_type& im (sts.image ());" << "binding& imb (sts.out_image_binding ());" @@ -2321,10 +2363,10 @@ namespace relational // grow () // os << "bool " << traits << "::" << endl - << "grow (image_type& i, my_bool* e)" + << "grow (image_type& i, " << truncated_vector << " t)" << "{" << "ODB_POTENTIALLY_UNUSED (i);" - << "ODB_POTENTIALLY_UNUSED (e);" + << "ODB_POTENTIALLY_UNUSED (t);" << endl << "bool grew (false);" << endl; @@ -2339,7 +2381,7 @@ namespace relational // bind (image_type) // os << "void " << traits << "::" << endl - << "bind (MYSQL_BIND* b, image_type& i)" + << "bind (" << bind_vector << " b, image_type& i)" << "{" << "ODB_POTENTIALLY_UNUSED (b);" << "ODB_POTENTIALLY_UNUSED (i);" @@ -2418,6 +2460,56 @@ namespace relational instance schema_drop_; instance schema_create_; }; + + struct include: virtual context + { + typedef include base; + + virtual void + generate () + { + os << "#include " << endl; + + if (embedded_schema) + os << "#include " << endl; + + os << "#include " << endl; + + if (options.generate_query ()) + os << "#include " << endl; + + os << endl; + + extra_pre (); + + os << "#include " << endl + << "#include " << endl + << "#include " << endl + << "#include " << endl + << "#include " << endl + << "#include " << endl + << "#include " << endl + << "#include " << endl + << "#include " << endl; + + if (options.generate_query ()) + os << "#include " << endl; + + extra_post (); + + os << endl; + } + + virtual void + extra_pre () + { + } + + virtual void + extra_post () + { + } + }; } } diff --git a/odb/relational/sqlite/context.cxx b/odb/relational/sqlite/context.cxx index 2e888e3..6ed1740 100644 --- a/odb/relational/sqlite/context.cxx +++ b/odb/relational/sqlite/context.cxx @@ -73,6 +73,9 @@ namespace relational assert (current_ == 0); current_ = this; + data_->bind_vector_ = "sqlite::bind*"; + data_->truncated_vector_ = "bool*"; + // Populate the C++ type to DB type map. // for (size_t i (0); i < sizeof (type_map) / sizeof (type_map_entry); ++i) diff --git a/odb/relational/sqlite/source.cxx b/odb/relational/sqlite/source.cxx index 360e220..418a5e3 100644 --- a/odb/relational/sqlite/source.cxx +++ b/odb/relational/sqlite/source.cxx @@ -103,7 +103,7 @@ namespace relational << b << ".buffer = " << arg << "." << mi.var << "value.data ();" << b << ".size = &" << arg << "." << mi.var << "size;" << b << ".capacity = " << arg << "." << mi.var << - "value.capacity ());" + "value.capacity ();" << b << ".is_null = &" << arg << "." << mi.var << "null;"; } @@ -114,7 +114,7 @@ namespace relational << b << ".buffer = " << arg << "." << mi.var << "value.data ();" << b << ".size = &" << arg << "." << mi.var << "size;" << b << ".capacity = " << arg << "." << mi.var << - "value.capacity ());" + "value.capacity ();" << b << ".is_null = &" << arg << "." << mi.var << "null;"; } @@ -144,7 +144,7 @@ namespace relational return false; ostringstream ostr; - ostr << "e[" << index_ << "UL]"; + ostr << "t[" << index_ << "UL]"; e = ostr.str (); if (var_override_.empty ()) @@ -168,7 +168,7 @@ namespace relational { os << "if (composite_value_traits< " << mi.fq_type () << " >::grow (" << endl - << "i." << mi.var << "value, e + " << index_ << "UL))" + << "i." << mi.var << "value, t + " << index_ << "UL))" << "{" << "grew = true;" << "}"; @@ -557,6 +557,18 @@ namespace relational member_database_type_id member_database_type_id_; }; entry init_value_member_; + + struct class_: relational::class_, context + { + class_ (base const& x): base (x) {} + + virtual void + init_auto_id (semantics::data_member&, string const& im) + { + os << im << "null = true;"; + } + }; + entry class_entry_; } } } -- cgit v1.1