From 823026b58211a4166de06ac243d978dcb9930271 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Mon, 22 Jan 2024 15:58:08 +0300 Subject: Turn odb repository into muti-package repository Also remove the autoconf/make-based build system. --- odb/relational/mysql/common.cxx | 400 ------------------ odb/relational/mysql/common.hxx | 171 -------- odb/relational/mysql/context.cxx | 868 --------------------------------------- odb/relational/mysql/context.hxx | 194 --------- odb/relational/mysql/header.cxx | 136 ------ odb/relational/mysql/inline.cxx | 42 -- odb/relational/mysql/model.cxx | 161 -------- odb/relational/mysql/schema.cxx | 489 ---------------------- odb/relational/mysql/source.cxx | 724 -------------------------------- 9 files changed, 3185 deletions(-) delete mode 100644 odb/relational/mysql/common.cxx delete mode 100644 odb/relational/mysql/common.hxx delete mode 100644 odb/relational/mysql/context.cxx delete mode 100644 odb/relational/mysql/context.hxx delete mode 100644 odb/relational/mysql/header.cxx delete mode 100644 odb/relational/mysql/inline.cxx delete mode 100644 odb/relational/mysql/model.cxx delete mode 100644 odb/relational/mysql/schema.cxx delete mode 100644 odb/relational/mysql/source.cxx (limited to 'odb/relational/mysql') 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 - -#include - -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_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_; - - // - // 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_; - } -} 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 -#include - -namespace relational -{ - namespace mysql - { - struct member_base: virtual relational::member_base_impl, 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 -#include - -#include -#include - -#include -#include - -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 (root_context::data_.get ()), m), - data_ (static_cast (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 ("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 (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 ("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 (&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 (&t)) - { - semantics::type& bt (a->base_type ()); - if (bt.is_a ()) - { - 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") : 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 -#include - -#include - -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 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 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 - -#include -#include - -namespace relational -{ - namespace mysql - { - namespace header - { - namespace relational = relational::header; - - struct image_member: relational::image_member_impl, - 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_; - } - } -} 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 - -#include -#include - -using namespace std; - -namespace relational -{ - namespace mysql - { - namespace inline_ - { - namespace relational = relational::inline_; - - struct null_member: relational::null_member_impl, - 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_; - } - } -} diff --git a/odb/relational/mysql/model.cxx b/odb/relational/mysql/model.cxx deleted file mode 100644 index 17ed4c0..0000000 --- a/odb/relational/mysql/model.cxx +++ /dev/null @@ -1,161 +0,0 @@ -// file : odb/relational/mysql/model.cxx -// license : GNU GPL v3; see accompanying LICENSE file - -#include - -#include -#include - -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 (*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 (er.value ()); - - return ostr.str (); - } - } - }; - entry object_columns_; - - struct member_create: relational::member_create, context - { - member_create (base const& x): base (x) {} - - virtual string - table_options (semantics::data_member& m, semantics::type& c) - { - string r (relational::member_create::table_options (m, c)); - - string const& engine (options.mysql_engine ()); - if (engine != "default") - { - // Note: MySQL table options can be separated with spaces. - // - if (!r.empty ()) - r += ' '; - - r += "ENGINE="; - r += engine; - } - - return r; - } - }; - entry member_create_; - - struct class_: relational::class_, context - { - class_ (base const& x): base (x) {} - - virtual string - table_options (type& c) - { - string r (relational::class_::table_options (c)); - - string const& engine (options.mysql_engine ()); - if (engine != "default") - { - // Note: MySQL table options can be separated with spaces. - // - if (!r.empty ()) - r += ' '; - - r += "ENGINE="; - r += engine; - } - - return r; - } - }; - entry 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 - -#include -#include - -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 (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_; - - 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 (in.scope ())); - - os << "DROP INDEX " << name (in) << " ON " << - quote_id (t.name ()) << endl; - } - }; - entry 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_; - - 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_; - - 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_; - - 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 (&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 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_; - - // - // 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_; - - 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 (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 (&i->nameable ())) - { - foreign_key& fk (find (*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 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_; - - 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 (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 (&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 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_; - - // - // 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_; - } - } -} 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 - -#include -#include - -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::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_; - - 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_; - - // - // bind - // - - struct bind_member: relational::bind_member_impl, - 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 (" << 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 (" << 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 (" << 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 (" << 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 (" << endl - << arg << "." << mi.var << "value.capacity ());" - << b << ".length = &" << arg << "." << mi.var << "size;" - << b << ".is_null = &" << arg << "." << mi.var << "null;"; - } - }; - entry bind_member_; - - // - // grow - // - - struct grow_member: relational::grow_member_impl, - 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_; - - // - // init image - // - - struct init_image_member: relational::init_image_member_impl, - 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 (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 (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 (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 (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 (size);" - << "grew = grew || (cap != i." << mi.var << "value.capacity ());"; - } - }; - entry init_image_member_; - - // - // init value - // - - struct init_value_member: relational::init_value_member_impl, - 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_; - - 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 id; - // - semantics::type& t (utype (m)); - if (wrapper (t) && t.template get ("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_entry_; - - struct include: relational::include, context - { - include (base const& x): base (x) {} - - virtual void - extra_post () - { - os << "#include " << endl; - } - }; - entry include_; - } - } -} -- cgit v1.1