From 30d797ffff4a8e2492500aea2135567f91b15aa0 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 23 Jul 2010 14:42:52 +0200 Subject: Add generation of the image class definition --- odb/mysql/context.cxx | 193 ++++++++++-------- odb/mysql/context.hxx | 60 +++++- odb/mysql/header.cxx | 535 ++++++++++++++++++++++++++++++++++++++++---------- odb/mysql/inline.cxx | 68 +++---- odb/mysql/schema.cxx | 3 +- odb/mysql/source.cxx | 130 ++++++------ odb/tracer/header.cxx | 216 ++++++++++---------- odb/tracer/inline.cxx | 68 +++---- odb/tracer/source.cxx | 208 ++++++++++---------- 9 files changed, 948 insertions(+), 533 deletions(-) diff --git a/odb/mysql/context.cxx b/odb/mysql/context.cxx index 668ecf4..9f2373f 100644 --- a/odb/mysql/context.cxx +++ b/odb/mysql/context.cxx @@ -25,28 +25,28 @@ namespace mysql type_map_entry type_map[] = { - {"bool", "TINYINT(1)", 0}, + {"bool", "TINYINT(1) NOT NULL", 0}, - {"char", "TINYINT", 0}, - {"signed char", "TINYINT", 0}, - {"unsigned char", "TINYINT UNSIGNED", 0}, + {"char", "TINYINT NOT NULL", 0}, + {"signed char", "TINYINT NOT NULL", 0}, + {"unsigned char", "TINYINT UNSIGNED NOT NULL", 0}, - {"short int", "SMALLINT", 0}, - {"short unsigned int", "SMALLINT UNSIGNED", 0}, + {"short int", "SMALLINT NOT NULL", 0}, + {"short unsigned int", "SMALLINT UNSIGNED NOT NULL", 0}, - {"int", "INT", 0}, - {"unsigned int", "INT UNSIGNED", 0}, + {"int", "INT NOT NULL", 0}, + {"unsigned int", "INT UNSIGNED NOT NULL", 0}, - {"long int", "BIGINT", 0}, - {"long unsigned int", "BIGINT UNSIGNED", 0}, + {"long int", "BIGINT NOT NULL", 0}, + {"long unsigned int", "BIGINT UNSIGNED NOT NULL", 0}, - {"long long int", "BIGINT", 0}, - {"long long unsigned int", "BIGINT UNSIGNED", 0}, + {"long long int", "BIGINT NOT NULL", 0}, + {"long long unsigned int", "BIGINT UNSIGNED NOT NULL", 0}, - {"float", "FLOAT", 0}, - {"double", "DOUBLE", 0}, + {"float", "FLOAT NOT NULL", 0}, + {"double", "DOUBLE NOT NULL", 0}, - {"::std::string", "TEXT", "VARCHAR(255)"} + {"::std::string", "TEXT NOT NULL", "VARCHAR(255) NOT NULL"} }; } @@ -110,14 +110,17 @@ namespace mysql { parse_prefix, parse_name, - parse_bounds, - parse_sign + parse_range, + parse_sign, + parse_done }; state s (parse_prefix); + string prefix; for (sql_token t (l.next ()); - t.type () != sql_token::t_eos; t = l.next ()) + s != parse_done && t.type () != sql_token::t_eos; + t = l.next ()) { sql_token::token_type tt (t.type ()); @@ -134,14 +137,15 @@ namespace mysql id == "CHARACTER" || id == "LONG") { - r.type = id; + prefix = id; + s = parse_name; continue; } } // Fall through. // - s = parse_prefix; + s = parse_name; } case parse_name: { @@ -154,180 +158,178 @@ namespace mysql // if (id == "BIT") { - r.type = "BIT"; + r.type = sql_type::BIT; } else if (id == "TINYINT" || id == "INT1") { - r.type = "TINYINT"; + r.type = sql_type::TINYINT; } else if (id == "BOOL" || id == "BOOLEAN") { - r.type = "TINYINT"; - r.bounds = true; - r.bounds_value = 1; + r.type = sql_type::TINYINT; + r.range = true; + r.range_value = 1; } else if (id == "SMALLINT" || id == "INT2") { - r.type = "SMALLINT"; + r.type = sql_type::SMALLINT; } else if (id == "MEDIUMINT" || id == "INT3" || id == "MIDDLEINT") { - r.type = "MEDIUMINT"; + r.type = sql_type::MEDIUMINT; } else if (id == "INT" || id == "INTEGER" || id == "INT4") { - r.type = "INT"; + r.type = sql_type::INT; } else if (id == "BIGINT" || id == "INT8") { - r.type = "BIGINT"; + r.type = sql_type::BIGINT; } else if (id == "SERIAL") { - r.type = "BIGINT"; + r.type = sql_type::BIGINT; r.unsign = true; } else if (id == "FLOAT" || id == "FLOAT4") { - r.type = "FLOAT"; + r.type = sql_type::FLOAT; } else if (id == "DOUBLE" || id == "FLOAT8") { - r.type = "DOUBLE"; + r.type = sql_type::DOUBLE; } else if (id == "DECIMAL" || id == "DEC" || id == "NUMERIC" || id == "FIXED") { - r.type = "DECIMAL"; + r.type = sql_type::DECIMAL; } // // Date-time types. // else if (id == "DATE") { - r.type = "DATE"; + r.type = sql_type::DATE; } else if (id == "TIME") { - r.type = "TIME"; + r.type = sql_type::TIME; } else if (id == "DATETIME") { - r.type = "DATETIME"; + r.type = sql_type::DATETIME; } else if (id == "TIMESTAMP") { - r.type = "TIMESTAMP"; + r.type = sql_type::TIMESTAMP; } else if (id == "YEAR") { - r.type = "YEAR"; + r.type = sql_type::YEAR; } // // String and binary types. // else if (id == "NCHAR") { - r.type = "CHAR"; + r.type = sql_type::CHAR; } else if (id == "VARCHAR") { - r.type = r.type == "LONG" ? "MEDIUMTEXT" : "VARCHAR"; + r.type = prefix == "LONG" + ? sql_type::MEDIUMTEXT + : sql_type::VARCHAR; } else if (id == "NVARCHAR") { - r.type = "VARCHAR"; + r.type = sql_type::VARCHAR; } - else if (id == "VARYING" && r.type == "CHARACTER") + else if (id == "VARYING" && prefix == "CHARACTER") { - r.type = "VARCHAR"; + r.type = sql_type::VARCHAR; } else if (id == "BINARY") { - r.type = "BINARY"; + r.type = sql_type::BINARY; } - else if (id == "BYTE" && r.type == "CHAR") + else if (id == "BYTE" && prefix == "CHAR") { - r.type = "BINARY"; + r.type = sql_type::BINARY; } else if (id == "VARBINARY") { - r.type = r.type == "LONG" ? "MEDIUMBLOB" : "VARBINARY"; + r.type = prefix == "LONG" + ? sql_type::MEDIUMBLOB + : sql_type::VARBINARY; } else if (id == "TINYBLOB") { - r.type = "TINYBLOB"; + r.type = sql_type::TINYBLOB; } else if (id == "TINYTEXT") { - r.type = "TINYTEXT"; + r.type = sql_type::TINYTEXT; } else if (id == "BLOB") { - r.type = "BLOB"; + r.type = sql_type::BLOB; } else if (id == "TEXT") { - r.type = "TEXT"; + r.type = sql_type::TEXT; } else if (id == "MEDIUMBLOB") { - r.type = "MEDIUMBLOB"; + r.type = sql_type::MEDIUMBLOB; } else if (id == "MEDIUMTEXT") { - r.type = "MEDIUMTEXT"; + r.type = sql_type::MEDIUMTEXT; } else if (id == "LONGBLOB") { - r.type = "LONGBLOB"; + r.type = sql_type::LONGBLOB; } else if (id == "LONGTEXT") { - r.type = "LONGTEXT"; + r.type = sql_type::LONGTEXT; } else if (id == "ENUM") { - r.type = "ENUM"; + r.type = sql_type::ENUM; } else if (id == "SET") { - r.type = "SET"; + r.type = sql_type::SET; } else match = false; if (match) { - s = parse_bounds; + s = parse_range; continue; } } - bool match (false); - // Some prefixes can also be type names if not followed // by the actual type name. // - if (!r.type.empty ()) + if (!prefix.empty ()) { - if (r.type == "CHAR") - match = true; - else if (r.type == "CHARACTER") + if (prefix == "CHAR" || prefix == "CHARACTER") { - r.type = "CHAR"; - match = true; + r.type = sql_type::CHAR; } - else if (r.type == "LONG") + else if (prefix == "LONG") { - r.type = "MEDIUMTEXT"; - match = true; + r.type = sql_type::MEDIUMTEXT; } } - if (!match) + if (r.type == sql_type::invalid) { cerr << m.file () << ":" << m.line () << ":" << m.column (); @@ -342,9 +344,9 @@ namespace mysql // Fall through. // - s = parse_bounds; + s = parse_range; } - case parse_bounds: + case parse_range: { if (t.punctuation () == sql_token::p_lparen) { @@ -353,7 +355,7 @@ namespace mysql if (t.type () != sql_token::t_int_lit) { cerr << m.file () << ":" << m.line () << ":" << m.column () - << " error: integer bounds expected in MySQL type " + << " error: integer range expected in MySQL type " << "declaration" << endl; throw generation_failed (); @@ -365,20 +367,20 @@ namespace mysql if (!(is >> v && is.eof ())) { cerr << m.file () << ":" << m.line () << ":" << m.column () - << " error: invalid bounds value '" << t.literal () + << " error: invalid range value '" << t.literal () << "'in MySQL type declaration" << endl; throw generation_failed (); } - r.bounds = true; - r.bounds_value = v; + r.range = true; + r.range_value = v; t = l.next (); if (t.punctuation () == sql_token::p_comma) { - // We have the second bounds value. Skip it. + // We have the second range value. Skip it. // l.next (); t = l.next (); @@ -408,15 +410,44 @@ namespace mysql r.unsign = true; } - return r; + s = parse_done; + break; } } } - cerr << m.file () << ":" << m.line () << ":" << m.column () - << " error: empty MySQL type declaration" << endl; + if (s == parse_name && !prefix.empty ()) + { + // Some prefixes can also be type names if not followed + // by the actual type name. + // + if (prefix == "CHAR" || prefix == "CHARACTER") + { + r.type = sql_type::CHAR; + } + else if (prefix == "LONG") + { + r.type = sql_type::MEDIUMTEXT; + } + } - throw generation_failed (); + if (r.type == sql_type::invalid) + { + cerr << m.file () << ":" << m.line () << ":" << m.column () + << " error: incomplete MySQL type declaration" << endl; + + throw generation_failed (); + } + + // If range is omitted for CHAR or BIT types, it defaults to 1. + // + if ((r.type == sql_type::CHAR || r.type == sql_type::BIT) && !r.range) + { + r.range = true; + r.range_value = 1; + } + + return r; } catch (sql_lexer::invalid_input const& e) { diff --git a/odb/mysql/context.hxx b/odb/mysql/context.hxx index 7c075b2..bf01719 100644 --- a/odb/mysql/context.hxx +++ b/odb/mysql/context.hxx @@ -14,12 +14,64 @@ namespace mysql { struct sql_type { - sql_type () : unsign (false), bounds (false) {} + // Keep the order in each block of types. + // + enum core_type + { + // Integral types. + // + TINYINT, + SMALLINT, + MEDIUMINT, + INT, + BIGINT, + + // Float types. + // + FLOAT, + DOUBLE, + DECIMAL, + + // Data-time types. + // + DATE, + TIME, + DATETIME, + TIMESTAMP, + YEAR, + + // String and binary types. + // + CHAR, + BINARY, + VARCHAR, + VARBINARY, + TINYBLOB, + TINYTEXT, + BLOB, + TEXT, + MEDIUMBLOB, + MEDIUMTEXT, + LONGBLOB, + LONGTEXT, + + // Other types. + // + BIT, + ENUM, + SET, + + // Invalid type. + // + invalid + }; + + sql_type () : type (invalid), unsign (false), range (false) {} - std::string type; + core_type type; bool unsign; - bool bounds; - unsigned int bounds_value; // MySQL max value is 2^32 - 1 (LONGBLOG/TEXT). + bool range; + unsigned int range_value; // MySQL max value is 2^32 - 1 (LONGBLOG/TEXT). }; class context: public ::context diff --git a/odb/mysql/header.cxx b/odb/mysql/header.cxx index a4111ec..ad329d8 100644 --- a/odb/mysql/header.cxx +++ b/odb/mysql/header.cxx @@ -6,125 +6,454 @@ #include #include -namespace +namespace mysql { - struct class_: traversal::class_, context + namespace { - class_ (context& c) - : context (c) + const char* integer_types[] = + { + "char", + "short", + "int", + "int", + "long long" + }; + + const char* float_types[] = { - } + "float", + "double" + }; - virtual void - traverse (type& c) + struct image_member_base: traversal::data_member, context { - if (c.file () != unit.file ()) - return; + image_member_base (context& c) + : context (c) + { + } + + virtual void + traverse (type& m) + { + string const& name (m.name ()); + var = name + (name[name.size () - 1] == '_' ? "" : "_"); + + os << "// " << name << endl + << "//" << endl; + + sql_type const& t (db_type (m)); + + switch (t.type) + { + // Integral types. + // + case sql_type::TINYINT: + case sql_type::SMALLINT: + case sql_type::MEDIUMINT: + case sql_type::INT: + case sql_type::BIGINT: + { + traverse_integer (m, t); + break; + } + + // Float types. + // + case sql_type::FLOAT: + case sql_type::DOUBLE: + { + traverse_float (m, t); + break; + } + case sql_type::DECIMAL: + { + traverse_decimal (m, t); + break; + } + + // Data-time types. + // + case sql_type::DATE: + case sql_type::TIME: + case sql_type::DATETIME: + case sql_type::TIMESTAMP: + case sql_type::YEAR: + { + traverse_date_time (m, t); + break; + } + + // String and binary types. + // + case sql_type::CHAR: + case sql_type::VARCHAR: + case sql_type::TINYTEXT: + case sql_type::TEXT: + case sql_type::MEDIUMTEXT: + case sql_type::LONGTEXT: + { + // For string types the limit is in characters rather + // than in bytes. The fixed-length pre-allocated buffer + // optimization can only be used for 1-byte encodings. + // To support this we will need the character encoding + // in sql_type. + // + traverse_long_string (m, t); + break; + } + case sql_type::BINARY: + { + // BINARY's range is always 255 or less from MySQL 5.0.3. + // + traverse_short_string (m, t); + break; + } + case sql_type::VARBINARY: + case sql_type::TINYBLOB: + case sql_type::BLOB: + case sql_type::MEDIUMBLOB: + case sql_type::LONGBLOB: + { + if (t.range && t.range_value <= 255) + traverse_short_string (m, t); + else + traverse_long_string (m, t); + + break; + } + + // Other types. + // + case sql_type::BIT: + { + traverse_bit (m, t); + break; + } + case sql_type::ENUM: + { + traverse_enum (m, t); + break; + } + case sql_type::SET: + { + traverse_set (m, t); + break; + } + } + } + + virtual void + traverse_integer (type&, sql_type const&) + { + } + + virtual void + traverse_float (type&, sql_type const&) + { + } + + virtual void + traverse_decimal (type&, sql_type const&) + { + } - if (!c.count ("object")) - return; + virtual void + traverse_date_time (type&, sql_type const&) + { + } - string const& type (c.fq_name ()); + virtual void + traverse_short_string (type&, sql_type const&) + { + } - // Find the id member and type. - // - id_member t (*this); - t.traverse (c); + virtual void + traverse_long_string (type&, sql_type const&) + { + } - if (t.member () == 0) + virtual void + traverse_bit (type&, sql_type const&) { - cerr << c.file () << ":" << c.line () << ":" << c.column () - << " error: no data member designated as object id" << endl; + } - cerr << c.file () << ":" << c.line () << ":" << c.column () - << " info: use '#pragma odb id' to specify object id member" - << endl; + virtual void + traverse_enum (type&, sql_type const&) + { + } - throw generation_failed (); + virtual void + traverse_set (type&, sql_type const&) + { } - semantics::data_member& id (*t.member ()); - semantics::type& id_type (id.type ()); + protected: + string var; + }; + + struct image_member: image_member_base + { + image_member (context& c) + : image_member_base (c) + { + } - if (id_type.anonymous ()) + virtual void + traverse_integer (type&, sql_type const& t) { - // Can be a template-id (which we should handle eventually) or an - // anonymous type in member declaration (e.g., struct {...} m_;). + if (t.unsign) + os << "unsigned "; + else if (t.type == sql_type::TINYINT) + os << "signed "; + + os << integer_types[t.type - sql_type::TINYINT] << " " << + var << "value;" + << "my_bool " << var << "null;" + << endl; + } + + virtual void + traverse_float (type&, sql_type const& t) + { + os << float_types[t.type - sql_type::FLOAT] << " " << var << "value;" + << "my_bool " << var << "null;" + << endl; + } + + virtual void + traverse_decimal (type&, sql_type const& t) + { + // Exchanged as strings. Can have up to 65 digits not counting + // '-' and '.'. If range is not specified, the default is 10. // - cerr << id.file () << ":" << id.line () << ":" << id.column () - << " error: unnamed type in data member declaration" << endl; - - cerr << id.file () << ":" << id.line () << ":" << id.column () - << " info: use 'typedef' to name this type" - << endl; - - throw generation_failed (); - } - - os << "// " << c.name () << endl - << "//" << endl; - - os << "template <>" << endl - << "class access::object_traits< " << type << " >: " << endl - << " public access::object_memory< " << type << " >," << endl - << " public access::object_factory< " << type << " >" - << "{" - << "public:" << endl; - - // object_type & shared_ptr - // - os << "typedef " << type << " object_type;"; - - // id_type - // - os << "typedef " << id_type.fq_name () << " id_type;" - << endl; - - // id_source - // - os << "static const odb::id_source id_source = odb::ids_assigned;" - << endl; - - // id () - // - os << "static id_type" << endl - << "id (const object_type&);" - << endl; - - // persist () - // - os << "static void" << endl - << "persist (database&, object_type&);" - << endl; - - // store () - // - os << "static void" << endl - << "store (database&, object_type&);" - << endl; - - // erase () - // - os << "static void" << endl - << "erase (database&, const id_type&);" - << endl; - - // find () - // - os << "static pointer_type" << endl - << "find (database&, const id_type&);" - << endl; - - os << "static bool" << endl - << "find (database&, const id_type&, object_type&);"; - - os << "};"; - } - }; -} + os << "const char* " << var << "value;" + << "unsigned long " << var << "size;" + << "my_bool " << var << "null;" + << "char " << var << "buffer[" << + (t.range ? t.range_value : 10) + 3 << "];" + << endl; + } + + virtual void + traverse_date_time (type&, sql_type const& t) + { + if (t.type == sql_type::YEAR) + os << "short "; + else + os << "MYSQL_TIME "; + + os << var << "value;" + << "my_bool " << var << "null;" + << endl; + + } + + virtual void + traverse_short_string (type&, sql_type const& t) + { + // If range is not specified, the default buffer size is 255. + // + os << "const char* " << var << "value;" + << "unsigned long " << var << "size;" + << "my_bool " << var << "null;" + << "char " << var << "buffer[" << + (t.range ? t.range_value : 255) + 1 << "];" + << endl; + } + + virtual void + traverse_long_string (type&, sql_type const& t) + { + os << "const char* " << var << "value;" + << "unsigned long " << var << "size;" + << "my_bool " << var << "null;" + << "odb::buffer " << var << "buffer;" + << endl; + } + + virtual void + traverse_bit (type&, sql_type const& t) + { + // Valid range is 1 to 64. + // + unsigned int n (t.range / 8 + (t.range % 8 ? 1 : 0)); + + os << "unsigned char " << var << "value[" << n << "];" + << "my_bool " << var << "null;" + << endl; + } + + virtual void + traverse_enum (type&, sql_type const&) + { + // Represented as string. + // + os << "const char* " << var << "value;" + << "unsigned long " << var << "size;" + << "my_bool " << var << "null;" + << "odb::buffer " << var << "buffer;" + << endl; + } + + virtual void + traverse_set (type&, sql_type const&) + { + // Represented as string. + // + os << "const char* " << var << "value;" + << "unsigned long " << var << "size;" + << "my_bool " << var << "null;" + << "odb::buffer " << var << "buffer;" + << endl; + } + }; + + struct image_type: traversal::class_, context + { + image_type (context& c) + : context (c), image_member_ (c) + { + *this >> names_image_member_ >> image_member_; + } + + virtual void + traverse (type& c) + { + os << "struct image_type" + << "{"; + + names (c); + + os << "};"; + } + + private: + image_member image_member_; + traversal::names names_image_member_; + }; + + struct class_: traversal::class_, context + { + class_ (context& c) + : context (c), image_type_ (c) + { + } + + virtual void + traverse (type& c) + { + if (c.file () != unit.file ()) + return; + + if (!c.count ("object")) + return; + + string const& type (c.fq_name ()); + + // Find the id member and type. + // + id_member t (*this); + t.traverse (c); + + if (t.member () == 0) + { + cerr << c.file () << ":" << c.line () << ":" << c.column () + << " error: no data member designated as object id" << endl; + + cerr << c.file () << ":" << c.line () << ":" << c.column () + << " info: use '#pragma odb id' to specify object id member" + << endl; + + throw generation_failed (); + } + + semantics::data_member& id (*t.member ()); + semantics::type& id_type (id.type ()); + + if (id_type.anonymous ()) + { + // Can be a template-id (which we should handle eventually) or an + // anonymous type in member declaration (e.g., struct {...} m_;). + // + cerr << id.file () << ":" << id.line () << ":" << id.column () + << " error: unnamed type in data member declaration" << endl; + + cerr << id.file () << ":" << id.line () << ":" << id.column () + << " info: use 'typedef' to name this type" + << endl; + + throw generation_failed (); + } + + os << "// " << c.name () << endl + << "//" << endl; + + os << "template <>" << endl + << "class access::object_traits< " << type << " >: " << endl + << " public access::object_memory< " << type << " >," << endl + << " public access::object_factory< " << type << " >" + << "{" + << "public:" << endl; + + // object_type & shared_ptr + // + os << "typedef " << type << " object_type;"; + + // id_type + // + os << "typedef " << id_type.fq_name () << " id_type;" + << endl; + + // image_type + // + image_type_.traverse (c); + + // id_source + // + os << "static const odb::id_source id_source = odb::ids_assigned;" + << endl; + + // id () + // + os << "static id_type" << endl + << "id (const object_type&);" + << endl; + + // persist () + // + os << "static void" << endl + << "persist (database&, object_type&);" + << endl; + + // store () + // + os << "static void" << endl + << "store (database&, object_type&);" + << endl; + + // erase () + // + os << "static void" << endl + << "erase (database&, const id_type&);" + << endl; + + // find () + // + os << "static pointer_type" << endl + << "find (database&, const id_type&);" + << endl; + + os << "static bool" << endl + << "find (database&, const id_type&, object_type&);"; + + os << "};"; + } + + private: + image_type image_type_; + }; + } -namespace mysql -{ void generate_header (context& ctx) { @@ -141,8 +470,12 @@ namespace mysql ns >> ns_defines >> ns; ns_defines >> c; + ctx.os << "#include " << endl + << endl; + ctx.os << "#include " << endl << "#include " << endl + << "#include " << endl << endl; ctx.os << "namespace odb" diff --git a/odb/mysql/inline.cxx b/odb/mysql/inline.cxx index 44cf9d0..8388cac 100644 --- a/odb/mysql/inline.cxx +++ b/odb/mysql/inline.cxx @@ -6,50 +6,50 @@ #include #include -namespace +namespace mysql { - struct class_: traversal::class_, context + namespace { - class_ (context& c) - : context (c) + struct class_: traversal::class_, context { - } + class_ (context& c) + : context (c) + { + } - virtual void - traverse (type& c) - { - if (c.file () != unit.file ()) - return; + virtual void + traverse (type& c) + { + if (c.file () != unit.file ()) + return; - if (!c.count ("object")) - return; + if (!c.count ("object")) + return; - string const& type (c.fq_name ()); - string traits ("access::object_traits< " + type + " >"); + string const& type (c.fq_name ()); + string traits ("access::object_traits< " + type + " >"); - id_member t (*this); - t.traverse (c); - semantics::data_member& id (*t.member ()); + id_member t (*this); + t.traverse (c); + semantics::data_member& id (*t.member ()); - os << "// " << c.name () << endl - << "//" << endl - << endl; + os << "// " << c.name () << endl + << "//" << endl + << endl; - // id () - // - os << "inline" << endl - << traits << "::id_type" << endl - << traits << "::" << endl - << "id (const object_type& obj)" - << "{" - << "return obj." << id.name () << ";" << endl - << "}"; - } - }; -} + // id () + // + os << "inline" << endl + << traits << "::id_type" << endl + << traits << "::" << endl + << "id (const object_type& obj)" + << "{" + << "return obj." << id.name () << ";" << endl + << "}"; + } + }; + } -namespace mysql -{ void generate_inline (context& ctx) { diff --git a/odb/mysql/schema.cxx b/odb/mysql/schema.cxx index a38729e..4d25bdf 100644 --- a/odb/mysql/schema.cxx +++ b/odb/mysql/schema.cxx @@ -22,8 +22,7 @@ namespace else os << "," << endl; - os << " `" << column_name (m) << "` " << column_type (m) << - " NOT NULL"; + os << " `" << column_name (m) << "` " << column_type (m); if (m.count ("id")) os << " PRIMARY KEY"; diff --git a/odb/mysql/source.cxx b/odb/mysql/source.cxx index 0f117ec..5dfcf2e 100644 --- a/odb/mysql/source.cxx +++ b/odb/mysql/source.cxx @@ -6,76 +6,76 @@ #include #include -namespace +namespace mysql { - struct class_: traversal::class_, context + namespace { - class_ (context& c) - : context (c) + struct class_: traversal::class_, context { - } + class_ (context& c) + : context (c) + { + } - virtual void - traverse (type& c) - { - if (c.file () != unit.file ()) - return; - - if (!c.count ("object")) - return; - - string const& type (c.fq_name ()); - string traits ("access::object_traits< " + type + " >"); - - id_member t (*this); - t.traverse (c); - semantics::data_member& id (*t.member ()); - - os << "// " << c.name () << endl - << "//" << endl - << endl; - - // persist () - // - os << "void " << traits << "::" << endl - << "persist (database&, object_type& obj)" - << "{" - << "}"; - - // store () - // - os << "void " << traits << "::" << endl - << "store (database&, object_type& obj)" - << "{" - << "}"; - - // erase () - // - os << "void " << traits << "::" << endl - << "erase (database&, const id_type& id)" - << "{" - << "}"; - - // find () - // - os << traits << "::pointer_type" << endl - << traits << "::" << endl - << "find (database&, const id_type& id)" - << "{" - << "return 0;" - << "}"; - - os << "bool " << traits << "::" << endl - << "find (database&, const id_type& id, object_type& obj)" - << "{" - << "return false;" - << "}"; - } - }; -} + virtual void + traverse (type& c) + { + if (c.file () != unit.file ()) + return; + + if (!c.count ("object")) + return; + + string const& type (c.fq_name ()); + string traits ("access::object_traits< " + type + " >"); + + id_member t (*this); + t.traverse (c); + semantics::data_member& id (*t.member ()); + + os << "// " << c.name () << endl + << "//" << endl + << endl; + + // persist () + // + os << "void " << traits << "::" << endl + << "persist (database&, object_type& obj)" + << "{" + << "}"; + + // store () + // + os << "void " << traits << "::" << endl + << "store (database&, object_type& obj)" + << "{" + << "}"; + + // erase () + // + os << "void " << traits << "::" << endl + << "erase (database&, const id_type& id)" + << "{" + << "}"; + + // find () + // + os << traits << "::pointer_type" << endl + << traits << "::" << endl + << "find (database&, const id_type& id)" + << "{" + << "return 0;" + << "}"; + + os << "bool " << traits << "::" << endl + << "find (database&, const id_type& id, object_type& obj)" + << "{" + << "return false;" + << "}"; + } + }; + } -namespace mysql -{ void generate_source (context& ctx) { diff --git a/odb/tracer/header.cxx b/odb/tracer/header.cxx index c023e58..8c7254d 100644 --- a/odb/tracer/header.cxx +++ b/odb/tracer/header.cxx @@ -6,131 +6,131 @@ #include #include -namespace +namespace tracer { - struct class_: traversal::class_, context + namespace { - class_ (context& c) - : context (c) + struct class_: traversal::class_, context { - } + class_ (context& c) + : context (c) + { + } - virtual void - traverse (type& c) - { - if (c.file () != unit.file ()) - return; + virtual void + traverse (type& c) + { + if (c.file () != unit.file ()) + return; - if (!c.count ("object")) - return; + if (!c.count ("object")) + return; - string const& type (c.fq_name ()); + string const& type (c.fq_name ()); - // Find the id member and type. - // - id_member t (*this); - t.traverse (c); + // Find the id member and type. + // + id_member t (*this); + t.traverse (c); + + if (t.member () == 0) + { + cerr << c.file () << ":" << c.line () << ":" << c.column () + << " error: no data member designated as object id" << endl; + + cerr << c.file () << ":" << c.line () << ":" << c.column () + << " info: use '#pragma odb id' to specify object id member" + << endl; + + throw generation_failed (); + } + + semantics::data_member& id (*t.member ()); + semantics::type& id_type (id.type ()); + + if (id_type.anonymous ()) + { + // Can be a template-id (which we should handle eventually) or an + // anonymous type in member declaration (e.g., struct {...} m_;). + // + cerr << id.file () << ":" << id.line () << ":" << id.column () + << " error: unnamed type in data member declaration" << endl; + + cerr << id.file () << ":" << id.line () << ":" << id.column () + << " info: use 'typedef' to name this type" + << endl; + + throw generation_failed (); + } + + os << "// " << c.name () << endl + << "//" << endl; + + os << "template <>" << endl + << "class access::object_traits< " << type << " >: " << endl + << " public access::object_memory< " << type << " >," << endl + << " public access::object_factory< " << type << " >" + << "{" + << "public:" << endl; + + // object_type & shared_ptr + // + os << "typedef " << type << " object_type;"; - if (t.member () == 0) - { - cerr << c.file () << ":" << c.line () << ":" << c.column () - << " error: no data member designated as object id" << endl; + // id_type + // + os << "typedef " << id_type.fq_name () << " id_type;" + << endl; - cerr << c.file () << ":" << c.line () << ":" << c.column () - << " info: use '#pragma odb id' to specify object id member" - << endl; + // id_source + // + os << "static const odb::id_source id_source = odb::ids_assigned;" + << endl; - throw generation_failed (); - } + // type_name () + // + os << "static const char*" << endl + << "type_name ();" + << endl; - semantics::data_member& id (*t.member ()); - semantics::type& id_type (id.type ()); + // id () + // + os << "static id_type" << endl + << "id (const object_type&);" + << endl; - if (id_type.anonymous ()) - { - // Can be a template-id (which we should handle eventually) or an - // anonymous type in member declaration (e.g., struct {...} m_;). + // persist () // - cerr << id.file () << ":" << id.line () << ":" << id.column () - << " error: unnamed type in data member declaration" << endl; + os << "static void" << endl + << "persist (database&, object_type&);" + << endl; - cerr << id.file () << ":" << id.line () << ":" << id.column () - << " info: use 'typedef' to name this type" - << endl; + // store () + // + os << "static void" << endl + << "store (database&, object_type&);" + << endl; - throw generation_failed (); - } + // erase () + // + os << "static void" << endl + << "erase (database&, const id_type&);" + << endl; - os << "// " << c.name () << endl - << "//" << endl; - - os << "template <>" << endl - << "class access::object_traits< " << type << " >: " << endl - << " public access::object_memory< " << type << " >," << endl - << " public access::object_factory< " << type << " >" - << "{" - << "public:" << endl; - - // object_type & shared_ptr - // - os << "typedef " << type << " object_type;"; - - // id_type - // - os << "typedef " << id_type.fq_name () << " id_type;" - << endl; - - // id_source - // - os << "static const odb::id_source id_source = odb::ids_assigned;" - << endl; - - // type_name () - // - os << "static const char*" << endl - << "type_name ();" - << endl; - - // id () - // - os << "static id_type" << endl - << "id (const object_type&);" - << endl; - - // persist () - // - os << "static void" << endl - << "persist (database&, object_type&);" - << endl; - - // store () - // - os << "static void" << endl - << "store (database&, object_type&);" - << endl; - - // erase () - // - os << "static void" << endl - << "erase (database&, const id_type&);" - << endl; - - // find () - // - os << "static pointer_type" << endl - << "find (database&, const id_type&);" - << endl; - - os << "static bool" << endl - << "find (database&, const id_type&, object_type&);"; - - os << "};"; - } - }; -} + // find () + // + os << "static pointer_type" << endl + << "find (database&, const id_type&);" + << endl; + + os << "static bool" << endl + << "find (database&, const id_type&, object_type&);"; + + os << "};"; + } + }; + } -namespace tracer -{ void generate_header (context& ctx) { diff --git a/odb/tracer/inline.cxx b/odb/tracer/inline.cxx index 6beb8a8..ef8cf15 100644 --- a/odb/tracer/inline.cxx +++ b/odb/tracer/inline.cxx @@ -6,50 +6,50 @@ #include #include -namespace +namespace tracer { - struct class_: traversal::class_, context + namespace { - class_ (context& c) - : context (c) + struct class_: traversal::class_, context { - } + class_ (context& c) + : context (c) + { + } - virtual void - traverse (type& c) - { - if (c.file () != unit.file ()) - return; + virtual void + traverse (type& c) + { + if (c.file () != unit.file ()) + return; - if (!c.count ("object")) - return; + if (!c.count ("object")) + return; - string const& type (c.fq_name ()); - string traits ("access::object_traits< " + type + " >"); + string const& type (c.fq_name ()); + string traits ("access::object_traits< " + type + " >"); - id_member t (*this); - t.traverse (c); - semantics::data_member& id (*t.member ()); + id_member t (*this); + t.traverse (c); + semantics::data_member& id (*t.member ()); - os << "// " << c.name () << endl - << "//" << endl - << endl; + os << "// " << c.name () << endl + << "//" << endl + << endl; - // id () - // - os << "inline" << endl - << traits << "::id_type" << endl - << traits << "::" << endl - << "id (const object_type& obj)" - << "{" - << "return obj." << id.name () << ";" << endl - << "}"; - } - }; -} + // id () + // + os << "inline" << endl + << traits << "::id_type" << endl + << traits << "::" << endl + << "id (const object_type& obj)" + << "{" + << "return obj." << id.name () << ";" << endl + << "}"; + } + }; + } -namespace tracer -{ void generate_inline (context& ctx) { diff --git a/odb/tracer/source.cxx b/odb/tracer/source.cxx index e70adf1..696d707 100644 --- a/odb/tracer/source.cxx +++ b/odb/tracer/source.cxx @@ -6,115 +6,115 @@ #include #include -namespace +namespace tracer { - struct class_: traversal::class_, context + namespace { - class_ (context& c) - : context (c) + struct class_: traversal::class_, context { - } + class_ (context& c) + : context (c) + { + } - virtual void - traverse (type& c) - { - if (c.file () != unit.file ()) - return; - - if (!c.count ("object")) - return; - - string const& type (c.fq_name ()); - string traits ("access::object_traits< " + type + " >"); - - id_member t (*this); - t.traverse (c); - semantics::data_member& id (*t.member ()); - - os << "// " << c.name () << endl - << "//" << endl - << endl; - - // type_name () - // - os << "const char* " << traits << "::" << endl - << "type_name ()" - << "{" - << "return \"" << type << "\";" - << "}"; - - // persist () - // - os << "void " << traits << "::" << endl - << "persist (database&, object_type& obj)" - << "{" - << "std::cout << \"insert \" << type_name () << \" id \" << " << - "id (obj) << std::endl;" - << endl - << "if (id (obj) == id_type ())" << endl - << "throw object_already_persistent ();" - << "}"; - - // store () - // - os << "void " << traits << "::" << endl - << "store (database&, object_type& obj)" - << "{" - << "std::cout << \"update \" << type_name () << \" id \" << " << - "id (obj) << std::endl;" - << endl - << "if (id (obj) == id_type ())" << endl - << "throw object_not_persistent ();" - << "}"; - - // erase () - // - os << "void " << traits << "::" << endl - << "erase (database&, const id_type& id)" - << "{" - << "std::cout << \"delete \" << type_name () << \" id \" << " << - "id << std::endl;" - << endl - << "if (id == id_type ())" << endl - << "throw object_not_persistent ();" - << "}"; - - // find () - // - os << traits << "::pointer_type" << endl - << traits << "::" << endl - << "find (database&, const id_type& id)" - << "{" - << "std::cout << \"select \" << type_name () << \" id \" << " << - "id << std::endl;" - << endl - << "if (id == id_type ())" << endl - << "return pointer_type (0);" - << endl - << "pointer_type r (access::object_factory< " << type << - " >::create ());" - << "r->" << id.name () << " = id;" - << "return r;" - << "}"; - - os << "bool " << traits << "::" << endl - << "find (database&, const id_type& id, object_type& obj)" - << "{" - << "std::cout << \"select \" << type_name () << \" id \" << " << - "id << std::endl;" - << endl - << "if (id == id_type ())" << endl - << "return false;" - << endl - << "obj." << id.name () << " = id;" - << "return true;" - << "}"; - } - }; -} + virtual void + traverse (type& c) + { + if (c.file () != unit.file ()) + return; + + if (!c.count ("object")) + return; + + string const& type (c.fq_name ()); + string traits ("access::object_traits< " + type + " >"); + + id_member t (*this); + t.traverse (c); + semantics::data_member& id (*t.member ()); + + os << "// " << c.name () << endl + << "//" << endl + << endl; + + // type_name () + // + os << "const char* " << traits << "::" << endl + << "type_name ()" + << "{" + << "return \"" << type << "\";" + << "}"; + + // persist () + // + os << "void " << traits << "::" << endl + << "persist (database&, object_type& obj)" + << "{" + << "std::cout << \"insert \" << type_name () << \" id \" << " << + "id (obj) << std::endl;" + << endl + << "if (id (obj) == id_type ())" << endl + << "throw object_already_persistent ();" + << "}"; + + // store () + // + os << "void " << traits << "::" << endl + << "store (database&, object_type& obj)" + << "{" + << "std::cout << \"update \" << type_name () << \" id \" << " << + "id (obj) << std::endl;" + << endl + << "if (id (obj) == id_type ())" << endl + << "throw object_not_persistent ();" + << "}"; + + // erase () + // + os << "void " << traits << "::" << endl + << "erase (database&, const id_type& id)" + << "{" + << "std::cout << \"delete \" << type_name () << \" id \" << " << + "id << std::endl;" + << endl + << "if (id == id_type ())" << endl + << "throw object_not_persistent ();" + << "}"; + + // find () + // + os << traits << "::pointer_type" << endl + << traits << "::" << endl + << "find (database&, const id_type& id)" + << "{" + << "std::cout << \"select \" << type_name () << \" id \" << " << + "id << std::endl;" + << endl + << "if (id == id_type ())" << endl + << "return pointer_type (0);" + << endl + << "pointer_type r (access::object_factory< " << type << + " >::create ());" + << "r->" << id.name () << " = id;" + << "return r;" + << "}"; + + os << "bool " << traits << "::" << endl + << "find (database&, const id_type& id, object_type& obj)" + << "{" + << "std::cout << \"select \" << type_name () << \" id \" << " << + "id << std::endl;" + << endl + << "if (id == id_type ())" << endl + << "return false;" + << endl + << "obj." << id.name () << " = id;" + << "return true;" + << "}"; + } + }; + } -namespace tracer -{ void generate_source (context& ctx) { -- cgit v1.1