aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2010-07-23 14:42:52 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2010-07-23 14:42:52 +0200
commit30d797ffff4a8e2492500aea2135567f91b15aa0 (patch)
tree53fa570844ab3876026ec6621b40c74547e1db24
parentcea6fb57ac8c9a893c0f404fef6c1469f0b6222b (diff)
Add generation of the image class definition
-rw-r--r--odb/mysql/context.cxx193
-rw-r--r--odb/mysql/context.hxx60
-rw-r--r--odb/mysql/header.cxx535
-rw-r--r--odb/mysql/inline.cxx68
-rw-r--r--odb/mysql/schema.cxx3
-rw-r--r--odb/mysql/source.cxx130
-rw-r--r--odb/tracer/header.cxx216
-rw-r--r--odb/tracer/inline.cxx68
-rw-r--r--odb/tracer/source.cxx208
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 <odb/mysql/common.hxx>
#include <odb/mysql/header.hxx>
-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 <mysql/mysql.h>" << endl
+ << endl;
+
ctx.os << "#include <odb/core.hxx>" << endl
<< "#include <odb/traits.hxx>" << endl
+ << "#include <odb/buffer.hxx>" << 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 <odb/mysql/common.hxx>
#include <odb/mysql/inline.hxx>
-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 <odb/mysql/common.hxx>
#include <odb/mysql/source.hxx>
-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 <odb/common.hxx>
#include <odb/tracer/header.hxx>
-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 <odb/common.hxx>
#include <odb/tracer/inline.hxx>
-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 <odb/common.hxx>
#include <odb/tracer/source.hxx>
-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)
{