summaryrefslogtreecommitdiff
path: root/odb/relational/mysql
diff options
context:
space:
mode:
Diffstat (limited to 'odb/relational/mysql')
-rw-r--r--odb/relational/mysql/common.cxx400
-rw-r--r--odb/relational/mysql/common.hxx171
-rw-r--r--odb/relational/mysql/context.cxx868
-rw-r--r--odb/relational/mysql/context.hxx194
-rw-r--r--odb/relational/mysql/header.cxx136
-rw-r--r--odb/relational/mysql/inline.cxx42
-rw-r--r--odb/relational/mysql/model.cxx135
-rw-r--r--odb/relational/mysql/schema.cxx489
-rw-r--r--odb/relational/mysql/source.cxx724
9 files changed, 0 insertions, 3159 deletions
diff --git a/odb/relational/mysql/common.cxx b/odb/relational/mysql/common.cxx
deleted file mode 100644
index d049443..0000000
--- a/odb/relational/mysql/common.cxx
+++ /dev/null
@@ -1,400 +0,0 @@
-// file : odb/relational/mysql/common.cxx
-// license : GNU GPL v3; see accompanying LICENSE file
-
-#include <cassert>
-
-#include <odb/relational/mysql/common.hxx>
-
-using namespace std;
-
-namespace relational
-{
- namespace mysql
- {
- //
- // member_base
- //
-
- sql_type const& member_base::
- member_sql_type (semantics::data_member& m)
- {
- return parse_sql_type (column_type (m, key_prefix_), m);
- }
-
- void member_base::
- traverse_simple (member_info& mi)
- {
- switch (mi.st->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 (mi);
- break;
- }
-
- // Float types.
- //
- case sql_type::FLOAT:
- case sql_type::DOUBLE:
- {
- traverse_float (mi);
- break;
- }
- case sql_type::DECIMAL:
- {
- traverse_decimal (mi);
- 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 (mi);
- 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 (mi);
- break;
- }
- case sql_type::BINARY:
- case sql_type::TINYBLOB:
- {
- // BINARY's range is always 255 or less from MySQL 5.0.3.
- // TINYBLOB can only store up to 255 bytes.
- //
- traverse_short_string (mi);
- break;
- }
- case sql_type::VARBINARY:
- case sql_type::BLOB:
- case sql_type::MEDIUMBLOB:
- case sql_type::LONGBLOB:
- {
- if (mi.st->range && mi.st->range_value <= 255)
- traverse_short_string (mi);
- else
- traverse_long_string (mi);
-
- break;
- }
-
- // Other types.
- //
- case sql_type::BIT:
- {
- traverse_bit (mi);
- break;
- }
- case sql_type::ENUM:
- {
- traverse_enum (mi);
- break;
- }
- case sql_type::SET:
- {
- traverse_set (mi);
- break;
- }
- case sql_type::invalid:
- {
- assert (false);
- break;
- }
- }
- }
-
- //
- // member_image_type
- //
-
- static const char* integer_types[] =
- {
- "char",
- "short",
- "int",
- "int",
- "long long"
- };
-
- static const char* float_types[] =
- {
- "float",
- "double"
- };
-
- member_image_type::
- member_image_type (base const& x)
- : member_base::base (x), // virtual base
- base (x) {}
-
- member_image_type::
- member_image_type ()
- : relational::member_base (0, 0, string (), string ()) {}
-
- member_image_type::
- member_image_type (semantics::type* type,
- const custom_cxx_type* ct,
- string const& fq_type,
- string const& key_prefix)
- : relational::member_base (type, ct, fq_type, key_prefix) {}
-
- string member_image_type::
- image_type (semantics::data_member& m)
- {
- type_.clear ();
- member_base::traverse (m, true);
- return type_;
- }
-
- void member_image_type::
- traverse_composite (member_info& mi)
- {
- type_ = "composite_value_traits< " + mi.fq_type () +
- ", id_mysql >::image_type";
- }
-
- void member_image_type::
- traverse_integer (member_info& mi)
- {
- if (mi.st->unsign)
- type_ = "unsigned ";
- else if (mi.st->type == sql_type::TINYINT)
- type_ = "signed ";
-
- type_ += integer_types[mi.st->type - sql_type::TINYINT];
- }
-
- void member_image_type::
- traverse_float (member_info& mi)
- {
- type_ = float_types[mi.st->type - sql_type::FLOAT];
- }
-
- void member_image_type::
- traverse_decimal (member_info&)
- {
- type_ = "details::buffer";
- }
-
- void member_image_type::
- traverse_date_time (member_info& mi)
- {
- if (mi.st->type == sql_type::YEAR)
- type_ = "short";
- else
- type_ = "MYSQL_TIME";
- }
-
- void member_image_type::
- traverse_string (member_info&)
- {
- type_ = "details::buffer";
- }
-
- void member_image_type::
- traverse_bit (member_info&)
- {
- type_ = "unsigned char*";
- }
-
- void member_image_type::
- traverse_enum (member_info& mi)
- {
- // Represented as either integer or string.
- //
- type_ = "mysql::value_traits< " + mi.fq_type () +
- ", mysql::id_enum >::image_type";
- }
-
- void member_image_type::
- traverse_set (member_info&)
- {
- // Represented as string.
- //
- type_ = "details::buffer";
- }
-
- entry<member_image_type> member_image_type_;
-
- //
- // member_database_type
- //
-
- static const char* integer_database_id[] =
- {
- "id_tiny",
- "id_utiny",
- "id_short",
- "id_ushort",
- "id_long", // INT24
- "id_ulong", // INT24 UNSIGNED
- "id_long",
- "id_ulong",
- "id_longlong",
- "id_ulonglong"
- };
-
- static const char* float_database_id[] =
- {
- "id_float",
- "id_double"
- };
-
- static const char* date_time_database_id[] =
- {
- "id_date",
- "id_time",
- "id_datetime",
- "id_timestamp",
- "id_year"
- };
-
- static const char* char_bin_database_id[] =
- {
- "id_string", // CHAR
- "id_blob", // BINARY,
- "id_string", // VARCHAR
- "id_blob", // VARBINARY
- "id_string", // TINYTEXT
- "id_blob", // TINYBLOB
- "id_string", // TEXT
- "id_blob", // BLOB
- "id_string", // MEDIUMTEXT
- "id_blob", // MEDIUMBLOB
- "id_string", // LONGTEXT
- "id_blob" // LONGBLOB
- };
-
- member_database_type_id::
- member_database_type_id (base const& x)
- : member_base::base (x), // virtual base
- base (x) {}
-
- member_database_type_id::
- member_database_type_id ()
- : member_base::base (0, 0, string (), string ()), // virtual base
- base (0, 0, string (), string ()) {}
-
- member_database_type_id::
- member_database_type_id (semantics::type* type,
- const custom_cxx_type* ct,
- string const& fq_type,
- string const& key_prefix)
- : member_base::base (type, ct, fq_type, key_prefix), // virtual base
- base (type, ct, fq_type, key_prefix) {}
-
- string member_database_type_id::
- database_type_id (type& m)
- {
- type_id_.clear ();
- member_base::traverse (m, true);
- return type_id_;
- }
-
- void member_database_type_id::
- traverse_composite (member_info&)
- {
- assert (false);
- }
-
- void member_database_type_id::
- traverse_integer (member_info& mi)
- {
- size_t i (
- (mi.st->type - sql_type::TINYINT) * 2 + (mi.st->unsign ? 1 : 0));
- type_id_ = string ("mysql::") + integer_database_id[i];
- }
-
- void member_database_type_id::
- traverse_float (member_info& mi)
- {
- type_id_ = string ("mysql::") +
- float_database_id[mi.st->type - sql_type::FLOAT];
- }
-
- void member_database_type_id::
- traverse_decimal (member_info&)
- {
- type_id_ = "mysql::id_decimal";
- }
-
- void member_database_type_id::
- traverse_date_time (member_info& mi)
- {
- type_id_ = string ("mysql::") +
- date_time_database_id[mi.st->type - sql_type::DATE];
- }
-
- void member_database_type_id::
- traverse_string (member_info& mi)
- {
- type_id_ = string ("mysql::") +
- char_bin_database_id[mi.st->type - sql_type::CHAR];
- }
-
- void member_database_type_id::
- traverse_bit (member_info&)
- {
- type_id_ = "mysql::id_bit";
- }
-
- void member_database_type_id::
- traverse_enum (member_info&)
- {
- type_id_ = "mysql::id_enum";
- }
-
- void member_database_type_id::
- traverse_set (member_info&)
- {
- type_id_ = "mysql::id_set";
- }
-
- entry<member_database_type_id> member_database_type_id_;
-
- //
- // query_columns
- //
-
- struct query_columns: relational::query_columns, context
- {
- query_columns (base const& x): base_impl (x) {}
-
- virtual string
- database_type_id (semantics::data_member& m)
- {
- return member_database_type_id_.database_type_id (m);
- }
-
- private:
- member_database_type_id member_database_type_id_;
- };
- entry<query_columns> query_columns_;
- }
-}
diff --git a/odb/relational/mysql/common.hxx b/odb/relational/mysql/common.hxx
deleted file mode 100644
index b43dc0d..0000000
--- a/odb/relational/mysql/common.hxx
+++ /dev/null
@@ -1,171 +0,0 @@
-// file : odb/relational/mysql/common.hxx
-// license : GNU GPL v3; see accompanying LICENSE file
-
-#ifndef ODB_RELATIONAL_MYSQL_COMMON_HXX
-#define ODB_RELATIONAL_MYSQL_COMMON_HXX
-
-#include <odb/relational/common.hxx>
-#include <odb/relational/mysql/context.hxx>
-
-namespace relational
-{
- namespace mysql
- {
- struct member_base: virtual relational::member_base_impl<sql_type>, context
- {
- member_base (base const& x): base (x), base_impl (x) {}
-
- // This c-tor is for the direct use inside the mysql namespace.
- // If you do use this c-tor, you should also explicitly call
- // relational::member_base (aka base).
- //
- member_base () {}
-
- virtual sql_type const&
- member_sql_type (semantics::data_member&);
-
- virtual void
- traverse_simple (member_info&);
-
- virtual void
- traverse_integer (member_info&)
- {
- }
-
- virtual void
- traverse_float (member_info&)
- {
- }
-
- virtual void
- traverse_decimal (member_info&)
- {
- }
-
- virtual void
- traverse_date_time (member_info&)
- {
- }
-
- virtual void
- traverse_string (member_info&)
- {
- }
-
- virtual void
- traverse_short_string (member_info& mi)
- {
- traverse_string (mi);
- }
-
- virtual void
- traverse_long_string (member_info& mi)
- {
- traverse_string (mi);
- }
-
- virtual void
- traverse_bit (member_info&)
- {
- }
-
- virtual void
- traverse_enum (member_info&)
- {
- }
-
- virtual void
- traverse_set (member_info&)
- {
- }
- };
-
- struct member_image_type: relational::member_image_type,
- member_base
- {
- member_image_type (base const&);
- member_image_type ();
- member_image_type (semantics::type* type,
- const custom_cxx_type*,
- string const& fq_type = string (),
- string const& key_prefix = string ());
- virtual string
- image_type (semantics::data_member&);
-
- virtual void
- traverse_composite (member_info&);
-
- virtual void
- traverse_integer (member_info&);
-
- virtual void
- traverse_float (member_info&);
-
- virtual void
- traverse_decimal (member_info&);
-
- virtual void
- traverse_date_time (member_info&);
-
- virtual void
- traverse_string (member_info&);
-
- virtual void
- traverse_bit (member_info&);
-
- virtual void
- traverse_enum (member_info&);
-
- virtual void
- traverse_set (member_info&);
-
- private:
- string type_;
- };
-
- struct member_database_type_id: relational::member_database_type_id,
- member_base
- {
- member_database_type_id (base const&);
- member_database_type_id ();
- member_database_type_id (semantics::type* type,
- const custom_cxx_type*,
- string const& fq_type = string (),
- string const& key_prefix = string ());
-
- virtual string
- database_type_id (type&);
-
- virtual void
- traverse_composite (member_info&);
-
- virtual void
- traverse_integer (member_info&);
-
- virtual void
- traverse_float (member_info&);
-
- virtual void
- traverse_decimal (member_info&);
-
- virtual void
- traverse_date_time (member_info&);
-
- virtual void
- traverse_string (member_info&);
-
- virtual void
- traverse_bit (member_info&);
-
- virtual void
- traverse_enum (member_info&);
-
- virtual void
- traverse_set (member_info&);
-
- private:
- string type_id_;
- };
- }
-}
-#endif // ODB_RELATIONAL_MYSQL_COMMON_HXX
diff --git a/odb/relational/mysql/context.cxx b/odb/relational/mysql/context.cxx
deleted file mode 100644
index 8b3d983..0000000
--- a/odb/relational/mysql/context.cxx
+++ /dev/null
@@ -1,868 +0,0 @@
-// file : odb/relational/mysql/context.cxx
-// license : GNU GPL v3; see accompanying LICENSE file
-
-#include <cassert>
-#include <sstream>
-
-#include <odb/sql-token.hxx>
-#include <odb/sql-lexer.hxx>
-
-#include <odb/relational/mysql/context.hxx>
-#include <odb/relational/mysql/common.hxx>
-
-using namespace std;
-
-namespace relational
-{
- namespace mysql
- {
- namespace
- {
- struct type_map_entry
- {
- char const* const cxx_type;
- char const* const db_type;
- char const* const db_id_type;
- bool const null;
- };
-
- type_map_entry type_map[] =
- {
- {"bool", "TINYINT(1)", 0, false},
-
- {"char", "CHAR(1)", 0, false},
- {"signed char", "TINYINT", 0, false},
- {"unsigned char", "TINYINT UNSIGNED", 0, false},
-
- {"short int", "SMALLINT", 0, false},
- {"short unsigned int", "SMALLINT UNSIGNED", 0, false},
-
- {"int", "INT", 0, false},
- {"unsigned int", "INT UNSIGNED", 0, false},
-
- {"long int", "BIGINT", 0, false},
- {"long unsigned int", "BIGINT UNSIGNED", 0, false},
-
- {"long long int", "BIGINT", 0, false},
- {"long long unsigned int", "BIGINT UNSIGNED", 0, false},
-
- {"float", "FLOAT", 0, false},
- {"double", "DOUBLE", 0, false},
-
- {"::std::string", "TEXT", "VARCHAR(128)", false},
-
- {"::size_t", "BIGINT UNSIGNED", 0, false},
- {"::std::size_t", "BIGINT UNSIGNED", 0, false}
- };
- }
-
- context* context::current_;
-
- context::
- ~context ()
- {
- if (current_ == this)
- current_ = 0;
- }
-
- context::
- context (ostream& os,
- semantics::unit& u,
- options_type const& ops,
- features_type& f,
- sema_rel::model* m)
- : root_context (os, u, ops, f, data_ptr (new (shared) data (os))),
- base_context (static_cast<data*> (root_context::data_.get ()), m),
- data_ (static_cast<data*> (base_context::data_))
- {
- assert (current_ == 0);
- current_ = this;
-
- generate_grow = true;
- need_alias_as = true;
- insert_send_auto_id = true;
- delay_freeing_statement_result = false;
- need_image_clone = false;
- generate_bulk = false;
- global_index = false;
- global_fkey = true;
- 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)
- {
- type_map_entry const& e (type_map[i]);
-
- type_map_type::value_type v (
- e.cxx_type,
- db_type_type (
- e.db_type, e.db_id_type ? e.db_id_type : e.db_type, e.null));
-
- data_->type_map_.insert (v);
- }
- }
-
- context::
- context ()
- : data_ (current ().data_)
- {
- }
-
- string const& context::
- convert_expr (string const& sqlt, semantics::data_member& m, bool to)
- {
- sql_type const& t (parse_sql_type (sqlt, m));
- return to ? t.to : t.from;
- }
-
- string context::
- quote_id_impl (qname const& id) const
- {
- string r;
-
- bool f (true);
- for (qname::iterator i (id.begin ()); i < id.end (); ++i)
- {
- if (i->empty ())
- continue;
-
- // Warn if the name is greater than the 64 limit.
- //
- if (i->size () > 64)
- {
- cerr << "warning: SQL name '" << *i << "' is longer than "
- << "the MySQL name limit of 64 characters and will "
- << "be truncated" << endl;
-
- cerr << "info: consider shortening it using #pragma db "
- << "table/column/index or --*-regex options" << endl;
- }
-
- if (f)
- f = false;
- else
- r += '.';
-
- r += '`';
- r.append (*i, 0, 64); // Max identifier length is 64.
- r += '`';
- }
-
- return r;
- }
-
- namespace
- {
- struct has_grow: traversal::class_
- {
- has_grow (bool& r, user_section* s)
- : r_ (r), section_ (s)
- {
- *this >> inherits_ >> *this;
- }
-
- virtual void
- traverse (type& c)
- {
- bool view (context::view (c));
-
- // Ignore transient bases.
- //
- if (!(context::object (c) || view || context::composite (c)))
- return;
-
- if (section_ == 0 && c.count ("mysql-grow"))
- r_ = c.get<bool> ("mysql-grow");
- else
- {
- // r_ should be false.
- //
- if (!view)
- inherits (c);
-
- if (!r_)
- names (c);
-
- if (section_ == 0)
- c.set ("mysql-grow", r_);
- }
- }
-
- private:
- bool& r_;
- user_section* section_;
- traversal::inherits inherits_;
- };
-
- struct has_grow_member: member_base
- {
- has_grow_member (bool& r, user_section* section = 0)
- : relational::member_base (0, 0, string (), string (), section),
- r_ (r) {}
-
- has_grow_member (bool& r,
- user_section* section,
- semantics::type* t,
- const custom_cxx_type* ct,
- string const& key_prefix = string ())
- : relational::member_base (t, ct, string (), key_prefix, section),
- r_ (r) {}
-
- virtual bool
- pre (member_info& mi)
- {
- // If we have a key prefix (container), then it can't be in a
- // section (while mi.m can). The same for top-level -- if we got
- // called, then we shouldn't ignore it.
- //
- return !key_prefix_.empty () || top_level_ ||
- (section_ == 0 && !separate_load (mi.m)) ||
- (section_ != 0 && *section_ == section (mi.m));
- }
-
- virtual void
- traverse_composite (member_info& mi)
- {
- // By calling grow() instead of recursing, we reset any overrides.
- // We also don't pass section since they don't apply inside
- // composites.
- //
- r_ = r_ || context::grow (dynamic_cast<semantics::class_&> (mi.t));
- }
-
- virtual void
- traverse_decimal (member_info&)
- {
- r_ = true;
- }
-
- virtual void
- traverse_long_string (member_info&)
- {
- r_ = true;
- }
-
- virtual void
- traverse_short_string (member_info&)
- {
- r_ = true; // @@ Short string optimization disabled.
- }
-
- virtual void
- traverse_enum (member_info&)
- {
- r_ = true;
- }
-
- virtual void
- traverse_set (member_info&)
- {
- r_ = true;
- }
-
- private:
- bool& r_;
- };
- }
-
- bool context::
- grow_impl (semantics::class_& c, user_section* section)
- {
- if (section == 0 && c.count ("mysql-grow"))
- return c.get<bool> ("mysql-grow");
-
- bool r (false);
- has_grow ct (r, section);
- has_grow_member mt (r, section);
- traversal::names names;
- ct >> names >> mt;
- ct.traverse (c);
- return r;
- }
-
- bool context::
- grow_impl (semantics::data_member& m)
- {
- bool r (false);
- has_grow_member mt (r);
- mt.traverse (m, true);
- return r;
- }
-
- bool context::
- grow_impl (semantics::data_member& m,
- semantics::type& t,
- const custom_cxx_type* ct,
- string const& kp)
- {
- bool r (false);
- has_grow_member mt (r, 0, &t, ct, kp);
- mt.traverse (m, true);
- return r;
- }
-
- string context::
- database_type_impl (semantics::type& t,
- semantics::names* hint,
- bool id,
- bool* null)
- {
- using semantics::enum_;
- using semantics::enumerator;
- using semantics::array;
-
- string r;
-
- // Enum mapping.
- //
- if (enum_* e = dynamic_cast<enum_*> (&t))
- {
- // We can only map to ENUM if the C++ enumeration is contiguous
- // and starts with 0.
- //
- enum_::enumerates_iterator i (e->enumerates_begin ()),
- end (e->enumerates_end ());
-
- if (i != end)
- {
- r += "ENUM(";
-
- for (unsigned long long j (0); i != end; ++i, ++j)
- {
- enumerator const& er (i->enumerator ());
-
- if (er.value () != j)
- break;
-
- if (j != 0)
- r += ", ";
-
- r += quote_string (er.name ());
- }
-
- if (i == end)
- r += ")";
- else
- r.clear ();
- }
-
- if (!r.empty ())
- return r;
- }
-
- r = base_context::database_type_impl (t, hint, id, null);
-
- if (!r.empty ())
- return r;
-
- // char[N] mapping.
- //
- else if (array* a = dynamic_cast<array*> (&t))
- {
- semantics::type& bt (a->base_type ());
- if (bt.is_a<semantics::fund_char> ())
- {
- unsigned long long n (a->size ());
-
- if (n == 0)
- return r;
- else if (n == 1)
- r = "CHAR(";
- else
- {
- r = "VARCHAR(";
- n--;
- }
-
- ostringstream ostr;
- ostr << n;
- r += ostr.str ();
- r += ')';
- }
- }
-
- return r;
- }
-
- //
- // SQL type parsing.
- //
-
- sql_type const& context::
- parse_sql_type (string const& t, semantics::data_member& m, bool custom)
- {
- // If this proves to be too expensive, we can maintain a cache of
- // parsed types across contexts.
- //
- data::sql_type_cache::iterator i (data_->sql_type_cache_.find (t));
-
- if (i != data_->sql_type_cache_.end ()
- && (custom ? i->second.custom_cached : i->second.straight_cached))
- {
- return (custom ? i->second.custom : i->second.straight);
- }
- else
- {
- try
- {
- sql_type st (
- parse_sql_type (
- t,
- custom ? &unit.get<custom_db_types> ("custom-db-types") : 0));
-
- if (custom)
- return data_->sql_type_cache_[t].cache_custom (st);
- else
- return data_->sql_type_cache_[t].cache_straight (st);
- }
- catch (invalid_sql_type const& e)
- {
- cerr << m.file () << ":" << m.line () << ":" << m.column ()
- << ": error: " << e.message () << endl;
-
- throw operation_failed ();
- }
- }
- }
-
- inline sql_type
- error (bool fail, string const& m)
- {
- if (!fail)
- return sql_type ();
- else
- throw context::invalid_sql_type (m);
- }
-
- sql_type context::
- parse_sql_type (string sqlt, custom_db_types const* ct)
- {
- try
- {
- sql_type r;
-
- // First run the type through the custom mapping, if requested.
- //
- if (ct != 0)
- {
- for (custom_db_types::const_iterator i (ct->begin ());
- i != ct->end (); ++i)
- {
- custom_db_type const& t (*i);
-
- if (t.type.match (sqlt))
- {
- r.to = t.type.replace (sqlt, t.to);
- r.from = t.type.replace (sqlt, t.from);
- sqlt = t.type.replace (sqlt, t.as);
- break;
- }
- }
- }
-
- sql_lexer l (sqlt);
-
- // While most type names use single identifier, there are
- // a couple of exceptions to this rule:
- //
- // NATIONAL CHAR|VARCHAR
- // CHAR BYTE (BINARY)
- // CHARACTER VARYING (VARCHAR)
- // LONG VARBINARY (MEDIUMBLOB)
- // LONG VARCHAR (MEDIUMTEXT)
- //
- //
- enum state
- {
- parse_prefix,
- parse_name,
- parse_range,
- parse_sign,
- parse_done
- };
-
- state s (parse_prefix);
- string prefix;
- bool flt (false);
-
- for (sql_token t (l.next ());
- s != parse_done && t.type () != sql_token::t_eos;
- t = l.next ())
- {
- sql_token::token_type tt (t.type ());
-
- switch (s)
- {
- case parse_prefix:
- {
- if (tt == sql_token::t_identifier)
- {
- string const& id (context::upcase (t.identifier ()));
-
- if (id == "NATIONAL" ||
- id == "CHAR" ||
- id == "CHARACTER" ||
- id == "LONG")
- {
- prefix = id;
- s = parse_name;
- continue;
- }
- }
-
- s = parse_name;
- }
- // Fall through.
- case parse_name:
- {
- if (tt == sql_token::t_identifier)
- {
- bool match (true);
- string const& id (context::upcase (t.identifier ()));
-
- // Numeric types.
- //
- if (id == "BIT")
- {
- r.type = sql_type::BIT;
- }
- else if (id == "TINYINT" || id == "INT1")
- {
- r.type = sql_type::TINYINT;
- }
- else if (id == "BOOL" || id == "BOOLEAN")
- {
- r.type = sql_type::TINYINT;
- r.range = true;
- r.range_value = 1;
- }
- else if (id == "SMALLINT" || id == "INT2")
- {
- r.type = sql_type::SMALLINT;
- }
- else if (id == "MEDIUMINT" ||
- id == "INT3" ||
- id == "MIDDLEINT")
- {
- r.type = sql_type::MEDIUMINT;
- }
- else if (id == "INT" || id == "INTEGER" || id == "INT4")
- {
- r.type = sql_type::INT;
- }
- else if (id == "BIGINT" || id == "INT8")
- {
- r.type = sql_type::BIGINT;
- }
- else if (id == "SERIAL")
- {
- r.type = sql_type::BIGINT;
- r.unsign = true;
- }
- else if (id == "FLOAT")
- {
- // Assign a type only once we know the precision of the
- // float; it can be either 4 or 8 byte.
- //
- flt = true;
- }
- else if (id == "FLOAT4")
- {
- r.type = sql_type::FLOAT;
- }
- else if (id == "DOUBLE" || id == "FLOAT8")
- {
- r.type = sql_type::DOUBLE;
- }
- else if (id == "DECIMAL" ||
- id == "DEC" ||
- id == "NUMERIC" ||
- id == "FIXED")
- {
- r.type = sql_type::DECIMAL;
- }
- //
- // Date-time types.
- //
- else if (id == "DATE")
- {
- r.type = sql_type::DATE;
- }
- else if (id == "TIME")
- {
- r.type = sql_type::TIME;
- }
- else if (id == "DATETIME")
- {
- r.type = sql_type::DATETIME;
- }
- else if (id == "TIMESTAMP")
- {
- r.type = sql_type::TIMESTAMP;
- }
- else if (id == "YEAR")
- {
- r.type = sql_type::YEAR;
- }
- //
- // String and binary types.
- //
- else if (id == "NCHAR")
- {
- r.type = sql_type::CHAR;
- }
- else if (id == "VARCHAR")
- {
- r.type = prefix == "LONG"
- ? sql_type::MEDIUMTEXT
- : sql_type::VARCHAR;
- }
- else if (id == "NVARCHAR")
- {
- r.type = sql_type::VARCHAR;
- }
- else if (id == "VARYING" && prefix == "CHARACTER")
- {
- r.type = sql_type::VARCHAR;
- }
- else if (id == "BINARY")
- {
- r.type = sql_type::BINARY;
- }
- else if (id == "BYTE" && prefix == "CHAR")
- {
- r.type = sql_type::BINARY;
- }
- else if (id == "VARBINARY")
- {
- r.type = prefix == "LONG"
- ? sql_type::MEDIUMBLOB
- : sql_type::VARBINARY;
- }
- else if (id == "TINYBLOB")
- {
- r.type = sql_type::TINYBLOB;
- }
- else if (id == "TINYTEXT")
- {
- r.type = sql_type::TINYTEXT;
- }
- else if (id == "BLOB")
- {
- r.type = sql_type::BLOB;
- }
- else if (id == "TEXT")
- {
- r.type = sql_type::TEXT;
- }
- else if (id == "MEDIUMBLOB")
- {
- r.type = sql_type::MEDIUMBLOB;
- }
- else if (id == "MEDIUMTEXT")
- {
- r.type = sql_type::MEDIUMTEXT;
- }
- else if (id == "LONGBLOB")
- {
- r.type = sql_type::LONGBLOB;
- }
- else if (id == "LONGTEXT")
- {
- r.type = sql_type::LONGTEXT;
- }
- else if (id == "ENUM")
- {
- r.type = sql_type::ENUM;
- }
- else if (id == "SET")
- {
- r.type = sql_type::SET;
- }
- else
- match = false;
-
- if (match)
- {
- s = parse_range;
- continue;
- }
- }
-
- // Some prefixes can also be type names if not followed
- // by the actual type name.
- //
- if (!prefix.empty ())
- {
- if (prefix == "CHAR" || prefix == "CHARACTER")
- {
- r.type = sql_type::CHAR;
- }
- else if (prefix == "LONG")
- {
- r.type = sql_type::MEDIUMTEXT;
- }
- }
-
- if (r.type == sql_type::invalid)
- {
- if (tt == sql_token::t_identifier)
- {
- return error (ct, "unknown MySQL type '" + t.identifier () +
- "'");
- }
- else
- return error (ct, "expected MySQL type name");
- }
-
- s = parse_range;
- }
- // Fall through.
- case parse_range:
- {
- if (t.punctuation () == sql_token::p_lparen)
- {
- t = l.next ();
-
- // ENUM and SET have a list of members instead of the range.
- //
- if (r.type == sql_type::ENUM || r.type == sql_type::SET)
- {
- while (true)
- {
- if (t.type () != sql_token::t_string_lit)
- {
- return error (ct, "string literal expected in MySQL "
- "ENUM or SET declaration");
- }
-
- if (r.type == sql_type::ENUM)
- r.enumerators.push_back (t.literal ());
-
- t = l.next ();
-
- if (t.punctuation () == sql_token::p_rparen)
- break;
- else if (t.punctuation () != sql_token::p_comma)
- {
- return error (ct, "comma expected in MySQL ENUM or "
- "SET declaration");
- }
-
- t = l.next ();
- }
- }
- else
- {
- if (t.type () != sql_token::t_int_lit)
- {
- return error (ct, "integer range expected in MySQL type "
- "declaration");
- }
-
- unsigned int v;
- istringstream is (t.literal ());
-
- if (!(is >> v && is.eof ()))
- {
- return error (ct, "invalid range value '" + t.literal () +
- "' in MySQL type declaration");
- }
-
- r.range = true;
- r.range_value = v;
-
- t = l.next ();
-
- if (t.punctuation () == sql_token::p_comma)
- {
- // We have the second range value. Skip it.
- //
- // In FLOAT the two-value range means something
- // completely different than the single-value.
- // Pretend we don't have the range in the former
- // case.
- //
- if (flt)
- r.range = false;
-
- l.next ();
- t = l.next ();
- }
- }
-
- if (t.punctuation () != sql_token::p_rparen)
- {
- return error (ct, "expected ')' in MySQL type declaration");
- }
-
- s = parse_sign;
- continue;
- }
-
- s = parse_sign;
- }
- // Fall through.
- case parse_sign:
- {
- if (tt == sql_token::t_identifier &&
- context::upcase (t.identifier ()) == "UNSIGNED")
- {
- r.unsign = true;
- }
-
- s = parse_done;
- break;
- }
- case parse_done:
- {
- assert (false);
- break;
- }
- }
- }
-
- 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;
- }
- }
-
- if (flt)
- {
- r.type = !r.range || r.range_value < 24
- ? sql_type::FLOAT
- : sql_type::DOUBLE;
- }
-
- if (r.type == sql_type::invalid)
- return error (ct, "incomplete MySQL type declaration");
-
- // 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)
- {
- return error (ct, "invalid MySQL type declaration: " + e.message);
- }
- }
- }
-}
diff --git a/odb/relational/mysql/context.hxx b/odb/relational/mysql/context.hxx
deleted file mode 100644
index 98574f2..0000000
--- a/odb/relational/mysql/context.hxx
+++ /dev/null
@@ -1,194 +0,0 @@
-// file : odb/relational/mysql/context.hxx
-// license : GNU GPL v3; see accompanying LICENSE file
-
-#ifndef ODB_RELATIONAL_MYSQL_CONTEXT_HXX
-#define ODB_RELATIONAL_MYSQL_CONTEXT_HXX
-
-#include <map>
-#include <vector>
-
-#include <odb/relational/context.hxx>
-
-namespace relational
-{
- namespace mysql
- {
- struct sql_type
- {
- // 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,
- TINYTEXT,
- TINYBLOB,
- TEXT,
- BLOB,
- MEDIUMTEXT,
- MEDIUMBLOB,
- LONGTEXT,
- LONGBLOB,
-
- // Other types.
- //
- BIT,
- ENUM,
- SET,
-
- // Invalid type.
- //
- invalid
- };
-
- sql_type () : type (invalid), unsign (false), range (false) {}
-
- core_type type;
- bool unsign;
- bool range;
- unsigned int range_value; // MySQL max value is 2^32 - 1 (LONGBLOG/TEXT).
- std::vector<std::string> enumerators; // Enumerator strings for ENUM.
-
- // Conversion expressions for custom database types.
- //
- std::string to;
- std::string from;
- };
-
- class context: public virtual relational::context
- {
- public:
- sql_type const&
- parse_sql_type (string const&,
- semantics::data_member&,
- bool custom = true);
- public:
- struct invalid_sql_type
- {
- invalid_sql_type (string const& message): message_ (message) {}
-
- string const&
- message () const {return message_;}
-
- private:
- string message_;
- };
-
- // If custom_db_types is NULL, then this function returns
- // invalid type instead of throwing in case an unknown type
- // is encountered.
- //
- static sql_type
- parse_sql_type (string, custom_db_types const* = 0);
-
- protected:
- virtual string const&
- convert_expr (string const&, semantics::data_member&, bool);
-
- virtual bool
- grow_impl (semantics::class_&, user_section*);
-
- virtual bool
- grow_impl (semantics::data_member&);
-
- virtual bool
- grow_impl (semantics::data_member&,
- semantics::type&,
- const custom_cxx_type*,
- string const&);
-
- protected:
- virtual string
- quote_id_impl (qname const&) const;
-
- protected:
- virtual string
- database_type_impl (semantics::type&, semantics::names*, bool, bool*);
-
- public:
- virtual
- ~context ();
- context ();
- context (std::ostream&,
- semantics::unit&,
- options_type const&,
- features_type&,
- sema_rel::model*);
-
- static context&
- current ()
- {
- return *current_;
- }
-
- private:
- static context* current_;
-
- private:
- struct data: base_context::data
- {
- data (std::ostream& os): base_context::data (os) {}
-
- struct sql_type_cache_entry
- {
- sql_type_cache_entry ()
- : custom_cached (false), straight_cached (false) {}
-
- sql_type const&
- cache_custom (sql_type const& t)
- {
- custom = t;
- custom_cached = true;
- return custom;
- }
-
- sql_type const&
- cache_straight (sql_type const& t)
- {
- straight = t;
- straight_cached = true;
- return straight;
- }
-
- sql_type custom; // With custom mapping.
- sql_type straight; // Without custom mapping.
-
- bool custom_cached;
- bool straight_cached;
- };
-
- typedef std::map<string, sql_type_cache_entry> sql_type_cache;
- sql_type_cache sql_type_cache_;
- };
- data* data_;
- };
- }
-}
-
-#endif // ODB_RELATIONAL_MYSQL_CONTEXT_HXX
diff --git a/odb/relational/mysql/header.cxx b/odb/relational/mysql/header.cxx
deleted file mode 100644
index 27bae48..0000000
--- a/odb/relational/mysql/header.cxx
+++ /dev/null
@@ -1,136 +0,0 @@
-// file : odb/relational/mysql/header.cxx
-// license : GNU GPL v3; see accompanying LICENSE file
-
-#include <odb/relational/header.hxx>
-
-#include <odb/relational/mysql/common.hxx>
-#include <odb/relational/mysql/context.hxx>
-
-namespace relational
-{
- namespace mysql
- {
- namespace header
- {
- namespace relational = relational::header;
-
- struct image_member: relational::image_member_impl<sql_type>,
- member_base
- {
- image_member (base const& x)
- : member_base::base (x), // virtual base
- member_base::base_impl (x), // virtual base
- base_impl (x),
- member_base (x) {}
-
- virtual void
- traverse_integer (member_info& mi)
- {
- os << image_type << " " << mi.var << "value;"
- << "my_bool " << mi.var << "null;"
- << endl;
- }
-
- virtual void
- traverse_float (member_info& mi)
- {
- os << image_type << " " << mi.var << "value;"
- << "my_bool " << mi.var << "null;"
- << endl;
- }
-
- virtual void
- traverse_decimal (member_info& mi)
- {
- // Exchanged as strings. Can have up to 65 digits not counting
- // '-' and '.'. If range is not specified, the default is 10.
- //
-
- /*
- @@ Disabled.
- os << "char " << mi.var << "value[" <<
- (t.range ? t.range_value : 10) + 3 << "];"
- */
-
- os << image_type << " " << mi.var << "value;"
- << "unsigned long " << mi.var << "size;"
- << "my_bool " << mi.var << "null;"
- << endl;
- }
-
- virtual void
- traverse_date_time (member_info& mi)
- {
- os << image_type << " " << mi.var << "value;"
- << "my_bool " << mi.var << "null;"
- << endl;
-
- }
-
- virtual void
- traverse_short_string (member_info& mi)
- {
- // If range is not specified, the default buffer size is 255.
- //
- /*
- @@ Disabled.
- os << "char " << mi.var << "value[" <<
- (t.range ? t.range_value : 255) + 1 << "];"
- */
-
- os << image_type << " " << mi.var << "value;"
- << "unsigned long " << mi.var << "size;"
- << "my_bool " << mi.var << "null;"
- << endl;
- }
-
- virtual void
- traverse_long_string (member_info& mi)
- {
- os << image_type << " " << mi.var << "value;"
- << "unsigned long " << mi.var << "size;"
- << "my_bool " << mi.var << "null;"
- << endl;
- }
-
- virtual void
- traverse_bit (member_info& mi)
- {
- // Valid range is 1 to 64.
- //
- unsigned int n (mi.st->range / 8 + (mi.st->range % 8 ? 1 : 0));
-
- os << "unsigned char " << mi.var << "value[" << n << "];"
- << "unsigned long " << mi.var << "size;"
- << "my_bool " << mi.var << "null;"
- << endl;
- }
-
- virtual void
- traverse_enum (member_info& mi)
- {
- // Represented as either integer or string. Since we don't know
- // at the code generation time which one it is, we have to always
- // keep size in case it is a string.
- //
- os << image_type << " " << mi.var << "value;"
- << "unsigned long " << mi.var << "size;"
- << "my_bool " << mi.var << "null;"
- << endl;
- }
-
- virtual void
- traverse_set (member_info& mi)
- {
- // Represented as string.
- //
- os << image_type << " " << mi.var << "value;"
- << "unsigned long " << mi.var << "size;"
- << "my_bool " << mi.var << "null;"
- << endl;
- }
- };
- entry<image_member> image_member_;
- }
- }
-}
diff --git a/odb/relational/mysql/inline.cxx b/odb/relational/mysql/inline.cxx
deleted file mode 100644
index bfa2c94..0000000
--- a/odb/relational/mysql/inline.cxx
+++ /dev/null
@@ -1,42 +0,0 @@
-// file : odb/relational/mysql/inline.cxx
-// license : GNU GPL v3; see accompanying LICENSE file
-
-#include <odb/relational/inline.hxx>
-
-#include <odb/relational/mysql/common.hxx>
-#include <odb/relational/mysql/context.hxx>
-
-using namespace std;
-
-namespace relational
-{
- namespace mysql
- {
- namespace inline_
- {
- namespace relational = relational::inline_;
-
- struct null_member: relational::null_member_impl<sql_type>,
- member_base
- {
- null_member (base const& x)
- : member_base::base (x), // virtual base
- member_base::base_impl (x), // virtual base
- base_impl (x),
- member_base (x)
- {
- }
-
- virtual void
- traverse_simple (member_info& mi)
- {
- if (get_)
- os << "r = r && i." << mi.var << "null;";
- else
- os << "i." << mi.var << "null = 1;";
- }
- };
- entry<null_member> null_member_;
- }
- }
-}
diff --git a/odb/relational/mysql/model.cxx b/odb/relational/mysql/model.cxx
deleted file mode 100644
index 2ec9d8b..0000000
--- a/odb/relational/mysql/model.cxx
+++ /dev/null
@@ -1,135 +0,0 @@
-// file : odb/relational/mysql/model.cxx
-// license : GNU GPL v3; see accompanying LICENSE file
-
-#include <sstream>
-
-#include <odb/relational/model.hxx>
-#include <odb/relational/mysql/context.hxx>
-
-using namespace std;
-
-namespace relational
-{
- namespace mysql
- {
- namespace model
- {
- namespace relational = relational::model;
-
- struct object_columns: relational::object_columns, context
- {
- object_columns (base const& x): base (x) {}
-
- virtual string
- default_bool (semantics::data_member&, bool v)
- {
- // MySQL has TRUE and FALSE as just aliases for 1 and 0. Still
- // use them for self-documentation.
- //
- return v ? "TRUE" : "FALSE";
- }
-
- virtual string
- default_enum (semantics::data_member& m, tree en, string const& name)
- {
- // Make sure the column is mapped to an ENUM or integer type.
- //
- sql_type const& t (parse_sql_type (column_type (), m, false));
-
- switch (t.type)
- {
- case sql_type::ENUM:
- case sql_type::TINYINT:
- case sql_type::SMALLINT:
- case sql_type::MEDIUMINT:
- case sql_type::INT:
- case sql_type::BIGINT:
- break;
- default:
- {
- cerr << m.file () << ":" << m.line () << ":" << m.column ()
- << ": error: column with default value specified as C++ "
- << "enumerator must map to MySQL ENUM or integer type"
- << endl;
-
- throw operation_failed ();
- }
- }
-
- using semantics::enum_;
- using semantics::enumerator;
-
- enumerator& er (dynamic_cast<enumerator&> (*unit.find (en)));
- enum_& e (er.enum_ ());
-
- if (t.type == sql_type::ENUM)
- {
- // Assuming the enumerators in the C++ enum and MySQL ENUM are
- // in the same order, calculate the poistion of the C++
- // enumerator and use that as an index in the MySQL ENUM.
- //
- size_t pos (0);
-
- for (enum_::enumerates_iterator i (e.enumerates_begin ()),
- end (e.enumerates_end ()); i != end; ++i)
- {
- if (&i->enumerator () == &er)
- break;
-
- pos++;
- }
-
- if (pos < t.enumerators.size ())
- return t.enumerators[pos];
- else
- {
- cerr << m.file () << ":" << m.line () << ":" << m.column ()
- << ": error: unable to map C++ enumerator '" << name
- << "' to MySQL ENUM value" << endl;
-
- throw operation_failed ();
- }
- }
- else
- {
- ostringstream ostr;
-
- if (e.unsigned_ ())
- ostr << er.value ();
- else
- ostr << static_cast<long long> (er.value ());
-
- return ostr.str ();
- }
- }
- };
- entry<object_columns> object_columns_;
-
- struct member_create: relational::member_create, context
- {
- member_create (base const& x): base (x) {}
-
- virtual string
- table_options (semantics::data_member&, semantics::type&)
- {
- string const& engine (options.mysql_engine ());
- return engine != "default" ? "ENGINE=" + engine : "";
- }
- };
- entry<member_create> member_create_;
-
- struct class_: relational::class_, context
- {
- class_ (base const& x): base (x) {}
-
- virtual string
- table_options (type&)
- {
- string const& engine (options.mysql_engine ());
- return engine != "default" ? "ENGINE=" + engine : "";
- }
- };
- entry<class_> class__;
- }
- }
-}
diff --git a/odb/relational/mysql/schema.cxx b/odb/relational/mysql/schema.cxx
deleted file mode 100644
index 60dc95b..0000000
--- a/odb/relational/mysql/schema.cxx
+++ /dev/null
@@ -1,489 +0,0 @@
-// file : odb/relational/mysql/schema.cxx
-// license : GNU GPL v3; see accompanying LICENSE file
-
-#include <odb/relational/schema.hxx>
-
-#include <odb/relational/mysql/common.hxx>
-#include <odb/relational/mysql/context.hxx>
-
-using namespace std;
-
-namespace relational
-{
- namespace mysql
- {
- namespace schema
- {
- namespace relational = relational::schema;
- using relational::table_set;
-
- //
- // Drop.
- //
-
- struct drop_foreign_key: relational::drop_foreign_key, context
- {
- drop_foreign_key (base const& x): base (x) {}
-
- virtual void
- drop (sema_rel::table& t, sema_rel::foreign_key& fk)
- {
- /*
- // @@ This does not work: in MySQL control statements can only
- // be used in stored procedures. It seems the only way to
- // implement this is to define, execute, and drop a stored
- // procedure, which is just too ugly.
- //
- // Another option would be to use CREATE TABLE IF NOT EXISTS
- // to create a dummy table with a dummy constraint that makes
- // the following DROP succeed. Note, however, that MySQL issues
- // a notice if the table already exist so would need to suppress
- // that as well. Still not sure that the utility of this support
- // justifies this kind of a hack.
- //
- os << "IF EXISTS (SELECT NULL FROM information_schema.TABLE_CONSTRAINTS" << endl
- << " WHERE CONSTRAINT_TYPE = " << quote_string ("FOREIGN KEY") << "AND" << endl
- << " CONSTRAINT_SCHEMA = DATABASE() AND" << endl
- << " CONSTRAINT_NAME = " << quote_string (fk.name ()) << ") THEN" << endl
- << " ALTER TABLE " << quote_id (t.name ()) << " DROP FOREIGN KEY " << quote_id (fk.name ()) << ";" << endl
- << "END IF;" << endl;
- */
-
- // So for now we only do this in migration.
- //
- if (dropped_ == 0)
- {
- if (fk.not_deferrable ())
- pre_statement ();
- else
- {
- if (format_ != schema_format::sql)
- return;
-
- os << "/*" << endl;
- }
-
- os << "ALTER TABLE " << quote_id (t.name ()) << endl
- << " DROP FOREIGN KEY " << quote_id (fk.name ()) << endl;
-
- if (fk.not_deferrable ())
- post_statement ();
- else
- os << "*/" << endl
- << endl;
- }
- }
-
- using base::drop;
-
- virtual void
- traverse (sema_rel::drop_foreign_key& dfk)
- {
- // Find the foreign key we are dropping in the base model.
- //
- sema_rel::foreign_key& fk (find<sema_rel::foreign_key> (dfk));
-
- if (fk.not_deferrable () || in_comment)
- base::traverse (dfk);
- else
- {
- if (format_ != schema_format::sql)
- return;
-
- os << endl
- << " /*"
- << endl;
-
- drop (dfk);
-
- os << endl
- << " */";
- }
- }
-
- virtual void
- drop_header ()
- {
- os << "DROP FOREIGN KEY ";
- }
- };
- entry<drop_foreign_key> drop_foreign_key_;
-
- struct drop_index: relational::drop_index, context
- {
- drop_index (base const& x): base (x) {}
-
- virtual void
- drop (sema_rel::index& in)
- {
- sema_rel::table& t (static_cast<sema_rel::table&> (in.scope ()));
-
- os << "DROP INDEX " << name (in) << " ON " <<
- quote_id (t.name ()) << endl;
- }
- };
- entry<drop_index> drop_index_;
-
- //
- // Create.
- //
-
- struct create_column: relational::create_column, context
- {
- create_column (base const& x): base (x) {}
-
- virtual void
- auto_ (sema_rel::primary_key&)
- {
- os << " AUTO_INCREMENT";
- }
- };
- entry<create_column> create_column_;
-
- struct create_foreign_key: relational::create_foreign_key, context
- {
- create_foreign_key (base const& x): base (x) {}
-
- void
- diagnose (sema_rel::foreign_key& fk)
- {
- if (fk.on_delete () != sema_rel::foreign_key::no_action)
- {
- cerr << "warning: foreign key '" << fk.name () << "' has " <<
- "ON DELETE clause but is disabled in MySQL due to lack "
- "of deferrable constraint support" << endl;
-
- cerr << "info: consider using non-deferrable foreign keys (" <<
- "--fkeys-deferrable-mode)" << endl;
- }
- }
-
- virtual void
- traverse_create (sema_rel::foreign_key& fk)
- {
- // MySQL does not support deferrable constraint checking. Output
- // such foreign keys as comments, for documentation, unless we
- // are generating embedded schema.
- //
- if (fk.not_deferrable ())
- base::traverse_create (fk);
- else
- {
- diagnose (fk);
-
- // Don't bloat C++ code with comment strings if we are
- // generating embedded schema.
- //
- if (format_ != schema_format::sql)
- return;
-
- os << endl
- << " /*" << endl
- << " CONSTRAINT ";
- create (fk);
- os << endl
- << " */";
- }
- }
-
- virtual void
- traverse_add (sema_rel::foreign_key& fk)
- {
- if (fk.not_deferrable () || in_comment)
- base::traverse_add (fk);
- else
- {
- diagnose (fk);
-
- if (format_ != schema_format::sql)
- return;
-
- os << endl
- << " /*"
- << endl;
-
- add (fk);
-
- os << endl
- << " */";
- }
- }
-
- virtual void
- deferrable (sema_rel::deferrable)
- {
- // This will still be called to output the comment.
- }
- };
- entry<create_foreign_key> create_foreign_key_;
-
- struct create_index: relational::create_index, context
- {
- create_index (base const& x): base (x) {}
-
- virtual void
- create (sema_rel::index& in)
- {
- os << "CREATE ";
-
- if (!in.type ().empty ())
- os << in.type () << ' ';
-
- os << "INDEX " << name (in);
-
- if (!in.method ().empty ())
- os << " USING " << in.method ();
-
- os << endl
- << " ON " << table_name (in) << " (";
-
- columns (in);
-
- os << ")" << endl;
-
- if (!in.options ().empty ())
- os << ' ' << in.options () << endl;
- }
- };
- entry<create_index> create_index_;
-
- struct create_table: relational::create_table, context
- {
- create_table (base const& x): base (x) {}
-
- // See if there are any undefined foreign keys that are not
- // deferrable.
- //
- bool
- check_undefined_fk_deferrable_only (sema_rel::table& t)
- {
- for (sema_rel::table::names_iterator i (t.names_begin ());
- i != t.names_end (); ++i)
- {
- using sema_rel::foreign_key;
-
- if (foreign_key* fk = dynamic_cast<foreign_key*> (&i->nameable ()))
- {
- if (!fk->count ("mysql-fk-defined") &&
- fk->not_deferrable ())
- return false;
- }
- }
- return true;
- }
-
- virtual void
- traverse (sema_rel::table& t)
- {
- if (pass_ == 1)
- base::traverse (t);
- else
- {
- // Add undefined foreign keys.
- //
- if (check_undefined_fk (t))
- {
- bool deferrable (check_undefined_fk_deferrable_only (t));
-
- if (!deferrable || format_ == schema_format::sql)
- {
- if (deferrable)
- {
- os << "/*" << endl;
- in_comment = true;
- }
- else
- pre_statement ();
-
- os << "ALTER TABLE " << quote_id (t.name ());
-
- instance<create_foreign_key> cfk (*this);
- trav_rel::unames n (*cfk);
- names (t, n);
- os << endl;
-
- if (deferrable)
- {
- in_comment = false;
- os << "*/" << endl
- << endl;
- }
- else
- post_statement ();
- }
- }
- }
- }
- };
- entry<create_table> create_table_;
-
- //
- // Alter.
- //
-
- struct alter_column: relational::alter_column, context
- {
- alter_column (base const& x): base (x) {}
-
- virtual void
- alter_header ()
- {
- os << "MODIFY COLUMN ";
- }
- };
- entry<alter_column> alter_column_;
-
- struct alter_table_pre: relational::alter_table_pre, context
- {
- alter_table_pre (base const& x): base (x) {}
-
- // Check if we are only dropping deferrable foreign keys.
- //
- bool
- check_drop_deferrable_only (sema_rel::alter_table& at)
- {
- if (check<sema_rel::add_column> (at) ||
- check_alter_column_null (at, true))
- return false;
-
- for (sema_rel::alter_table::names_iterator i (at.names_begin ());
- i != at.names_end (); ++i)
- {
- using sema_rel::foreign_key;
- using sema_rel::drop_foreign_key;
-
- if (drop_foreign_key* dfk =
- dynamic_cast<drop_foreign_key*> (&i->nameable ()))
- {
- foreign_key& fk (find<foreign_key> (*dfk));
-
- if (fk.not_deferrable ())
- return false;
- }
- }
- return true;
- }
-
- virtual void
- alter (sema_rel::alter_table& at)
- {
- if (check_drop_deferrable_only (at))
- {
- if (format_ != schema_format::sql)
- return;
-
- os << "/*" << endl;
- in_comment = true;
-
- os << "ALTER TABLE " << quote_id (at.name ());
- instance<drop_foreign_key> dfk (*this);
- trav_rel::unames n (*dfk);
- names (at, n);
- os << endl;
-
- in_comment = false;
- os << "*/" << endl
- << endl;
- }
- else
- base::alter (at);
- }
- };
- entry<alter_table_pre> alter_table_pre_;
-
- struct alter_table_post: relational::alter_table_post, context
- {
- alter_table_post (base const& x): base (x) {}
-
- // Check if we are only adding deferrable foreign keys.
- //
- bool
- check_add_deferrable_only (sema_rel::alter_table& at)
- {
- if (check<sema_rel::drop_column> (at) ||
- check_alter_column_null (at, false))
- return false;
-
- for (sema_rel::alter_table::names_iterator i (at.names_begin ());
- i != at.names_end (); ++i)
- {
- using sema_rel::add_foreign_key;
-
- if (add_foreign_key* afk =
- dynamic_cast<add_foreign_key*> (&i->nameable ()))
- {
- if (afk->not_deferrable ())
- return false;
- }
- }
- return true;
- }
-
- virtual void
- alter (sema_rel::alter_table& at)
- {
- if (check_add_deferrable_only (at))
- {
- if (format_ != schema_format::sql)
- return;
-
- os << "/*" << endl;
- in_comment = true;
-
- os << "ALTER TABLE " << quote_id (at.name ());
- instance<create_foreign_key> cfk (*this);
- trav_rel::unames n (*cfk);
- names (at, n);
- os << endl;
-
- in_comment = false;
- os << "*/" << endl
- << endl;
- }
- else
- base::alter (at);
- }
- };
- entry<alter_table_post> alter_table_post_;
-
- //
- // Schema version table.
- //
-
- struct version_table: relational::version_table, context
- {
- version_table (base const& x): base (x) {}
-
- virtual void
- create_table ()
- {
- pre_statement ();
-
- os << "CREATE TABLE IF NOT EXISTS " << qt_ << " (" << endl
- << " " << qn_ << " VARCHAR(128) NOT NULL PRIMARY KEY," << endl
- << " " << qv_ << " BIGINT UNSIGNED NOT NULL," << endl
- << " " << qm_ << " TINYINT(1) NOT NULL)" << endl;
-
- string const& engine (options.mysql_engine ());
- if (engine != "default")
- os << " ENGINE=" << engine << endl;
-
- post_statement ();
- }
-
- virtual void
- create (sema_rel::version v)
- {
- pre_statement ();
-
- os << "INSERT IGNORE INTO " << qt_ << " (" << endl
- << " " << qn_ << ", " << qv_ << ", " << qm_ << ")" << endl
- << " VALUES (" << qs_ << ", " << v << ", 0)" << endl;
-
- post_statement ();
- }
- };
- entry<version_table> version_table_;
- }
- }
-}
diff --git a/odb/relational/mysql/source.cxx b/odb/relational/mysql/source.cxx
deleted file mode 100644
index 9131ea7..0000000
--- a/odb/relational/mysql/source.cxx
+++ /dev/null
@@ -1,724 +0,0 @@
-// file : odb/relational/mysql/source.cxx
-// license : GNU GPL v3; see accompanying LICENSE file
-
-#include <odb/relational/source.hxx>
-
-#include <odb/relational/mysql/common.hxx>
-#include <odb/relational/mysql/context.hxx>
-
-using namespace std;
-
-namespace relational
-{
- namespace mysql
- {
- namespace source
- {
- namespace relational = relational::source;
-
- namespace
- {
- const char* integer_buffer_types[] =
- {
- "MYSQL_TYPE_TINY",
- "MYSQL_TYPE_SHORT",
- "MYSQL_TYPE_LONG", // *_bind_param() doesn't support INT24.
- "MYSQL_TYPE_LONG",
- "MYSQL_TYPE_LONGLONG"
- };
-
- const char* float_buffer_types[] =
- {
- "MYSQL_TYPE_FLOAT",
- "MYSQL_TYPE_DOUBLE"
- };
-
- const char* date_time_buffer_types[] =
- {
- "MYSQL_TYPE_DATE",
- "MYSQL_TYPE_TIME",
- "MYSQL_TYPE_DATETIME",
- "MYSQL_TYPE_TIMESTAMP",
- "MYSQL_TYPE_SHORT"
- };
-
- const char* char_bin_buffer_types[] =
- {
- "MYSQL_TYPE_STRING", // CHAR
- "MYSQL_TYPE_BLOB", // BINARY,
- "MYSQL_TYPE_STRING", // VARCHAR
- "MYSQL_TYPE_BLOB", // VARBINARY
- "MYSQL_TYPE_STRING", // TINYTEXT
- "MYSQL_TYPE_BLOB", // TINYBLOB
- "MYSQL_TYPE_STRING", // TEXT
- "MYSQL_TYPE_BLOB", // BLOB
- "MYSQL_TYPE_STRING", // MEDIUMTEXT
- "MYSQL_TYPE_BLOB", // MEDIUMBLOB
- "MYSQL_TYPE_STRING", // LONGTEXT
- "MYSQL_TYPE_BLOB" // LONGBLOB
- };
- }
-
- //
- //
- struct object_columns: relational::object_columns, context
- {
- object_columns (base const& x): base (x) {}
-
- virtual bool
- column (semantics::data_member& m,
- string const& table,
- string const& column)
- {
- // When we store a ENUM column in the MySQL database, if we bind
- // an integer parameter, then it is treated as an index and if we
- // bind a string, then it is treated as a enumerator. Everything
- // would have worked well if the same logic applied to the select
- // operation. That is, if we bind integer, then the database sends
- // the index and if we bind string then the database sends the
- // enumerator. Unfortunately, MySQL always sends the enumerator
- // and to get the index one has to resort to the enum+0 hack.
- //
- // This causes the following problem: at code generation time we
- // do not yet know which format we want. This is determined at
- // C++ compile time by traits (the reason we don't know this is
- // because we don't want to drag database-specific runtimes,
- // which define the necessary traits, as well as their
- // prerequisites into the ODB compilation process). As a result,
- // we cannot decide at code generation time whether we need the
- // +0 hack or not. One way to overcome this would be to construct
- // the SELECT statements at runtime, something along these lines:
- //
- // "enum" + enum_traits<type>::hack + ","
- //
- // However, this complicates the code generator quite a bit: we
- // either have to move to std::string storage for all the
- // statements and all the databases, which is kind of a waste,
- // or do some deep per-database customizations, which is hairy.
- // So, instead, we are going to use another hack (hey, what the
- // hell, right?) by loading both the index and enumerator
- // combined into a string:
- //
- // CONCAT (enum+0, ' ', enum)
- //
- // For cases where we need the index, everything works since
- // MySQL will convert the leading number and stop at the space.
- // For cases where we need the enumerator, we do a bit of pre-
- // processing (see enum_traits) before handing the value off
- // to value_traits.
- //
-
- string const& type (column_type ());
-
- if (sk_ != statement_select ||
- parse_sql_type (type, m).type != sql_type::ENUM)
- {
- return base::column (m, table, column);
- }
-
- // Qualified column and conversion expression.
- //
- string qc;
- if (!table.empty ())
- {
- qc += table;
- qc += '.';
- }
- qc += column;
- qc = convert_from (qc, type, m);
-
- string r ("CONCAT(" + qc + "+0,' '," + qc + ")");
-
- sc_.push_back (
- relational::statement_column (table, r, type, m, key_prefix_));
- return true;
- }
- };
- entry<object_columns> object_columns_;
-
- struct view_columns: relational::view_columns, context
- {
- view_columns (base const& x): base (x) {}
-
- virtual bool
- column (semantics::data_member& m,
- string const& table,
- string const& column)
- {
- // The same idea as in object_columns.
- //
- string const& type (column_type ());
-
- if (parse_sql_type (type, m).type != sql_type::ENUM)
- {
- return base::column (m, table, column);
- }
-
- // Column and conversion expression.
- //
- string c (convert_from (column, type, m));
-
- string r ("CONCAT(" + c + "+0,' '," + c + ")");
- sc_.push_back (relational::statement_column (table, r, type, m));
- return true;
- }
- };
- entry<view_columns> view_columns_;
-
- //
- // bind
- //
-
- struct bind_member: relational::bind_member_impl<sql_type>,
- member_base
- {
- bind_member (base const& x)
- : member_base::base (x), // virtual base
- member_base::base_impl (x), // virtual base
- base_impl (x),
- member_base (x)
- {
- }
-
- virtual void
- traverse_integer (member_info& mi)
- {
- // While the is_unsigned should indicate whether the
- // buffer variable is unsigned, rather than whether the
- // database type is unsigned, in case of the image types,
- // this is the same.
- //
- os << b << ".buffer_type = " <<
- integer_buffer_types[mi.st->type - sql_type::TINYINT] << ";"
- << b << ".is_unsigned = " << (mi.st->unsign ? "1" : "0") << ";"
- << b << ".buffer = &" << arg << "." << mi.var << "value;"
- << b << ".is_null = &" << arg << "." << mi.var << "null;";
- }
-
- virtual void
- traverse_float (member_info& mi)
- {
- os << b << ".buffer_type = " <<
- float_buffer_types[mi.st->type - sql_type::FLOAT] << ";"
- << b << ".buffer = &" << arg << "." << mi.var << "value;"
- << b << ".is_null = &" << arg << "." << mi.var << "null;";
- }
-
- virtual void
- traverse_decimal (member_info& mi)
- {
- os << b << ".buffer_type = MYSQL_TYPE_NEWDECIMAL;"
- << b << ".buffer = " << arg << "." << mi.var << "value.data ();"
- << b << ".buffer_length = static_cast<unsigned long> (" << endl
- << arg << "." << mi.var << "value.capacity ());"
- << b << ".length = &" << arg << "." << mi.var << "size;"
- << b << ".is_null = &" << arg << "." << mi.var << "null;";
- }
-
- virtual void
- traverse_date_time (member_info& mi)
- {
- os << b << ".buffer_type = " <<
- date_time_buffer_types[mi.st->type - sql_type::DATE] << ";"
- << b << ".buffer = &" << arg << "." << mi.var << "value;";
-
- if (mi.st->type == sql_type::YEAR)
- os << b << ".is_unsigned = 0;";
-
- os << b << ".is_null = &" << arg << "." << mi.var << "null;";
- }
-
- virtual void
- traverse_short_string (member_info& mi)
- {
- // MySQL documentation is quite confusing about the use of
- // buffer_length and length when it comes to input parameters.
- // Source code, however, tells us that it uses buffer_length
- // only if length is NULL.
- //
- os << b << ".buffer_type = " <<
- char_bin_buffer_types[mi.st->type - sql_type::CHAR] << ";"
- << b << ".buffer = " << arg << "." << mi.var << "value.data ();"
- << b << ".buffer_length = static_cast<unsigned long> (" << endl
- << arg << "." << mi.var << "value.capacity ());"
- << b << ".length = &" << arg << "." << mi.var << "size;"
- << b << ".is_null = &" << arg << "." << mi.var << "null;";
- }
-
- virtual void
- traverse_long_string (member_info& mi)
- {
- os << b << ".buffer_type = " <<
- char_bin_buffer_types[mi.st->type - sql_type::CHAR] << ";"
- << b << ".buffer = " << arg << "." << mi.var << "value.data ();"
- << b << ".buffer_length = static_cast<unsigned long> (" << endl
- << arg << "." << mi.var << "value.capacity ());"
- << b << ".length = &" << arg << "." << mi.var << "size;"
- << b << ".is_null = &" << arg << "." << mi.var << "null;";
- }
-
- virtual void
- traverse_bit (member_info& mi)
- {
- // Treated as a BLOB.
- //
- os << b << ".buffer_type = MYSQL_TYPE_BLOB;"
- << b << ".buffer = " << arg << "." << mi.var << "value;"
- << b << ".buffer_length = static_cast<unsigned long> (" << endl
- << "sizeof (" << arg << "." << mi.var << "value));"
- << b << ".length = &" << arg << "." << mi.var << "size;"
- << b << ".is_null = &" << arg << "." << mi.var << "null;";
- }
-
- virtual void
- traverse_enum (member_info& mi)
- {
- // Represented as either integer or string.
- //
- os << "mysql::enum_traits::bind (" << b << "," << endl
- << arg << "." << mi.var << "value," << endl
- << arg << "." << mi.var << "size," << endl
- << "&" << arg << "." << mi.var << "null);";
- }
-
- virtual void
- traverse_set (member_info& mi)
- {
- // Represented as a string.
- //
- os << b << ".buffer_type = MYSQL_TYPE_STRING;"
- << b << ".buffer = " << arg << "." << mi.var << "value.data ();"
- << b << ".buffer_length = static_cast<unsigned long> (" << endl
- << arg << "." << mi.var << "value.capacity ());"
- << b << ".length = &" << arg << "." << mi.var << "size;"
- << b << ".is_null = &" << arg << "." << mi.var << "null;";
- }
- };
- entry<bind_member> bind_member_;
-
- //
- // grow
- //
-
- struct grow_member: relational::grow_member_impl<sql_type>,
- member_base
- {
- grow_member (base const& x)
- : member_base::base (x), // virtual base
- member_base::base_impl (x), // virtual base
- base_impl (x),
- member_base (x) {}
-
- virtual void
- traverse_integer (member_info&)
- {
- os << e << " = 0;"
- << endl;
- }
-
- virtual void
- traverse_float (member_info&)
- {
- os << e << " = 0;"
- << endl;
- }
-
- virtual void
- traverse_decimal (member_info& mi)
- {
- // @@ Optimization disabled.
- //
- os << "if (" << e << ")" << endl
- << "{"
- << "i." << mi.var << "value.capacity (i." << mi.var << "size);"
- << "grew = true;"
- << "}";
- }
-
- virtual void
- traverse_date_time (member_info&)
- {
- os << e << " = 0;"
- << endl;
- }
-
- virtual void
- traverse_short_string (member_info& mi)
- {
- // @@ Optimization disabled.
- //
- os << "if (" << e << ")" << endl
- << "{"
- << "i." << mi.var << "value.capacity (i." << mi.var << "size);"
- << "grew = true;"
- << "}";
- }
-
- virtual void
- traverse_long_string (member_info& mi)
- {
- os << "if (" << e << ")" << endl
- << "{"
- << "i." << mi.var << "value.capacity (i." << mi.var << "size);"
- << "grew = true;"
- << "}";
- }
-
- virtual void
- traverse_bit (member_info&)
- {
- os << e << " = 0;"
- << endl;
- }
-
- virtual void
- traverse_enum (member_info& mi)
- {
- // Represented as either integer or string (and we don't know
- // at the code generation time which one it is).
- //
- os << "if (" << e << ")" << endl
- << "{"
- << "if (mysql::enum_traits::grow (" <<
- "i." << mi.var << "value, " <<
- "i." << mi.var << "size))" << endl
- << "grew = true;" // String
- << "else" << endl
- << e << " = 0;" // Integer.
- << "}";
- }
-
- virtual void
- traverse_set (member_info& mi)
- {
- // Represented as a string.
- //
- os << "if (" << e << ")" << endl
- << "{"
- << "i." << mi.var << "value.capacity (i." << mi.var << "size);"
- << "grew = true;"
- << "}";
- }
- };
- entry<grow_member> grow_member_;
-
- //
- // init image
- //
-
- struct init_image_member: relational::init_image_member_impl<sql_type>,
- member_base
- {
- init_image_member (base const& x)
- : member_base::base (x), // virtual base
- member_base::base_impl (x), // virtual base
- base_impl (x),
- member_base (x)
- {
- }
-
- virtual void
- set_null (member_info& mi)
- {
- os << "i." << mi.var << "null = 1;";
- }
-
- virtual void
- traverse_integer (member_info& mi)
- {
- os << traits << "::set_image (" << endl
- << "i." << mi.var << "value, is_null, " << member << ");"
- << "i." << mi.var << "null = is_null;";
- }
-
- virtual void
- traverse_float (member_info& mi)
- {
- os << traits << "::set_image (" << endl
- << "i." << mi.var << "value, is_null, " << member << ");"
- << "i." << mi.var << "null = is_null;";
- }
-
- virtual void
- traverse_decimal (member_info& mi)
- {
- // @@ Optimization: can remove growth check if buffer is fixed.
- //
- os << "std::size_t size (0);"
- << "std::size_t cap (i." << mi.var << "value.capacity ());"
- << traits << "::set_image (" << endl
- << "i." << mi.var << "value," << endl
- << "size," << endl
- << "is_null," << endl
- << member << ");"
- << "i." << mi.var << "null = is_null;"
- << "i." << mi.var << "size = static_cast<unsigned long> (size);"
- << "grew = grew || (cap != i." << mi.var << "value.capacity ());";
- }
-
- virtual void
- traverse_date_time (member_info& mi)
- {
- os << traits << "::set_image (" << endl
- << "i." << mi.var << "value, is_null, " << member << ");"
- << "i." << mi.var << "null = is_null;";
- }
-
- virtual void
- traverse_short_string (member_info& mi)
- {
- // @@ Optimization: can remove growth check if buffer is fixed.
- //
- os << "std::size_t size (0);"
- << "std::size_t cap (i." << mi.var << "value.capacity ());"
- << traits << "::set_image (" << endl
- << "i." << mi.var << "value," << endl
- << "size," << endl
- << "is_null," << endl
- << member << ");"
- << "i." << mi.var << "null = is_null;"
- << "i." << mi.var << "size = static_cast<unsigned long> (size);"
- << "grew = grew || (cap != i." << mi.var << "value.capacity ());";
- }
-
- virtual void
- traverse_long_string (member_info& mi)
- {
- os << "std::size_t size (0);"
- << "std::size_t cap (i." << mi.var << "value.capacity ());"
- << traits << "::set_image (" << endl
- << "i." << mi.var << "value," << endl
- << "size," << endl
- << "is_null," << endl
- << member << ");"
- << "i." << mi.var << "null = is_null;"
- << "i." << mi.var << "size = static_cast<unsigned long> (size);"
- << "grew = grew || (cap != i." << mi.var << "value.capacity ());";
- }
-
- virtual void
- traverse_bit (member_info& mi)
- {
- // Represented as a BLOB.
- //
- os << "std::size_t size (0);"
- << traits << "::set_image (" << endl
- << "i." << mi.var << "value," << endl
- << "sizeof (i." << mi.var << "value)," << endl
- << "size," << endl
- << "is_null," << endl
- << member << ");"
- << "i." << mi.var << "null = is_null;"
- << "i." << mi.var << "size = static_cast<unsigned long> (size);";
- }
-
- virtual void
- traverse_enum (member_info& mi)
- {
- // Represented as either integer or string.
- //
- os << "if (mysql::enum_traits::set_image (" << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "size," << endl
- << "is_null," << endl
- << member << "))" << endl
- << "grew = true;"
- << endl
- << "i." << mi.var << "null = is_null;";
- }
-
- virtual void
- traverse_set (member_info& mi)
- {
- // Represented as a string.
- //
- os << "std::size_t size (0);"
- << "std::size_t cap (i." << mi.var << "value.capacity ());"
- << traits << "::set_image (" << endl
- << "i." << mi.var << "value," << endl
- << "size," << endl
- << "is_null," << endl
- << member << ");"
- << "i." << mi.var << "null = is_null;"
- << "i." << mi.var << "size = static_cast<unsigned long> (size);"
- << "grew = grew || (cap != i." << mi.var << "value.capacity ());";
- }
- };
- entry<init_image_member> init_image_member_;
-
- //
- // init value
- //
-
- struct init_value_member: relational::init_value_member_impl<sql_type>,
- member_base
- {
- init_value_member (base const& x)
- : member_base::base (x), // virtual base
- member_base::base_impl (x), // virtual base
- base_impl (x),
- member_base (x)
- {
- }
-
- virtual void
- get_null (string const& var) const
- {
- os << "i." << var << "null";
- }
-
- virtual void
- traverse_integer (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "null);"
- << endl;
- }
-
- virtual void
- traverse_float (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "null);"
- << endl;
- }
-
- virtual void
- traverse_decimal (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "size," << endl
- << "i." << mi.var << "null);"
- << endl;
- }
-
- virtual void
- traverse_date_time (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "null);"
- << endl;
- }
-
- virtual void
- traverse_short_string (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "size," << endl
- << "i." << mi.var << "null);"
- << endl;
- }
-
- virtual void
- traverse_long_string (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "size," << endl
- << "i." << mi.var << "null);"
- << endl;
- }
-
- virtual void
- traverse_bit (member_info& mi)
- {
- // Represented as a BLOB.
- //
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "size," << endl
- << "i." << mi.var << "null);"
- << endl;
- }
-
- virtual void
- traverse_enum (member_info& mi)
- {
- // Represented as either integer or string.
- //
- os << "mysql::enum_traits::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "size," << endl
- << "i." << mi.var << "null);"
- << endl;
- }
-
- virtual void
- traverse_set (member_info& mi)
- {
- // Represented as a string.
- //
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "size," << endl
- << "i." << mi.var << "null);"
- << endl;
- }
- };
- entry<init_value_member> init_value_member_;
-
- struct class_: relational::class_, context
- {
- class_ (base const& x): base (x) {}
-
- virtual void
- init_auto_id (semantics::data_member& m, string const& im)
- {
- // Don't set the id value to 0 if this is a nullable wrapper. This
- // will allow the user to use the NO_AUTO_VALUE_ON_ZERO mode by
- // making it NULL when they want the auto semantics:
- //
- // #pragma db auto
- // odb::nullable<int64_t> id;
- //
- semantics::type& t (utype (m));
- if (wrapper (t) && t.template get<bool> ("wrapper-null-handler"))
- return;
-
- os << im << "value = 0;"
- << endl;
- }
-
- virtual string
- join_syntax (view_object const& vo)
- {
- if (vo.join == view_object::full)
- {
- error (vo.loc)
- << "FULL OUTER JOIN is not supported by MySQL" << endl;
- throw operation_failed ();
- }
-
- return base::join_syntax (vo);
- }
- };
- entry<class_> class_entry_;
-
- struct include: relational::include, context
- {
- include (base const& x): base (x) {}
-
- virtual void
- extra_post ()
- {
- os << "#include <odb/mysql/enum.hxx>" << endl;
- }
- };
- entry<include> include_;
- }
- }
-}