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/mssql/common.cxx | 603 ------------------- odb/relational/mssql/common.hxx | 293 ---------- odb/relational/mssql/context.cxx | 766 ------------------------ odb/relational/mssql/context.hxx | 194 ------ odb/relational/mssql/header.cxx | 312 ---------- odb/relational/mssql/inline.cxx | 42 -- odb/relational/mssql/model.cxx | 66 --- odb/relational/mssql/schema.cxx | 651 --------------------- odb/relational/mssql/source.cxx | 1201 -------------------------------------- 9 files changed, 4128 deletions(-) delete mode 100644 odb/relational/mssql/common.cxx delete mode 100644 odb/relational/mssql/common.hxx delete mode 100644 odb/relational/mssql/context.cxx delete mode 100644 odb/relational/mssql/context.hxx delete mode 100644 odb/relational/mssql/header.cxx delete mode 100644 odb/relational/mssql/inline.cxx delete mode 100644 odb/relational/mssql/model.cxx delete mode 100644 odb/relational/mssql/schema.cxx delete mode 100644 odb/relational/mssql/source.cxx (limited to 'odb/relational/mssql') diff --git a/odb/relational/mssql/common.cxx b/odb/relational/mssql/common.cxx deleted file mode 100644 index 1070d21..0000000 --- a/odb/relational/mssql/common.cxx +++ /dev/null @@ -1,603 +0,0 @@ -// file : odb/relational/mssql/common.cxx -// license : GNU GPL v3; see accompanying LICENSE file - -#include - -#include - -using namespace std; - -namespace relational -{ - namespace mssql - { - // - // 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) - { - const sql_type& st (*mi.st); - - // The same long/short data test as in context.cxx:long_data(). - // - switch (st.type) - { - // Integral types. - // - case sql_type::BIT: - case sql_type::TINYINT: - case sql_type::SMALLINT: - case sql_type::INT: - case sql_type::BIGINT: - { - traverse_integer (mi); - break; - } - - // Fixed and floating point types. - // - case sql_type::DECIMAL: - { - traverse_decimal (mi); - break; - } - case sql_type::SMALLMONEY: - { - traverse_smallmoney (mi); - break; - } - case sql_type::MONEY: - { - traverse_money (mi); - break; - } - case sql_type::FLOAT: - { - if (st.prec > 24) - traverse_float8 (mi); - else - traverse_float4 (mi); - - break; - } - - // String and binary types. - // - case sql_type::CHAR: - case sql_type::VARCHAR: - { - // Zero precision means max in VARCHAR(max). - // - if (st.prec == 0 || st.prec > options.mssql_short_limit ()) - traverse_long_string (mi); - else - traverse_string (mi); - - break; - } - case sql_type::TEXT: - { - traverse_long_string (mi); - break; - } - case sql_type::NCHAR: - case sql_type::NVARCHAR: - { - // Zero precision means max in NVARCHAR(max). Note that - // the precision is in 2-byte UCS-2 characters, not bytes. - // - if (st.prec == 0 || st.prec * 2 > options.mssql_short_limit ()) - traverse_long_nstring (mi); - else - traverse_nstring (mi); - - break; - } - case sql_type::NTEXT: - { - traverse_long_nstring (mi); - break; - } - case sql_type::BINARY: - case sql_type::VARBINARY: - { - // Zero precision means max in VARCHAR(max). - // - if (st.prec == 0 || st.prec > options.mssql_short_limit ()) - traverse_long_binary (mi); - else - traverse_binary (mi); - - break; - } - case sql_type::IMAGE: - { - traverse_long_binary (mi); - break; - } - - // Date-time types. - // - case sql_type::DATE: - { - traverse_date (mi); - break; - } - case sql_type::TIME: - { - traverse_time (mi); - break; - } - case sql_type::DATETIME: - case sql_type::DATETIME2: - case sql_type::SMALLDATETIME: - { - traverse_datetime (mi); - break; - } - case sql_type::DATETIMEOFFSET: - { - traverse_datetimeoffset (mi); - break; - } - - // Other types. - // - case sql_type::UNIQUEIDENTIFIER: - { - traverse_uniqueidentifier (mi); - break; - } - case sql_type::ROWVERSION: - { - traverse_rowversion (mi); - break; - } - case sql_type::invalid: - { - assert (false); - break; - } - } - } - - // - // member_image_type - // - - static const char* integer_types[] = - { - "unsigned char", - "unsigned char", - "short", - "int", - "long long" - }; - - 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_mssql >::image_type"; - } - - void member_image_type:: - traverse_integer (member_info& mi) - { - type_ = integer_types[mi.st->type - sql_type::BIT]; - } - - void member_image_type:: - traverse_decimal (member_info&) - { - type_ = "mssql::decimal"; - } - - void member_image_type:: - traverse_smallmoney (member_info&) - { - type_ = "mssql::smallmoney"; - } - - void member_image_type:: - traverse_money (member_info&) - { - type_ = "mssql::money"; - } - - void member_image_type:: - traverse_float4 (member_info&) - { - type_ = "float"; - } - - void member_image_type:: - traverse_float8 (member_info&) - { - type_ = "double"; - } - - void member_image_type:: - traverse_string (member_info&) - { - type_ = "char*"; - } - - void member_image_type:: - traverse_long_string (member_info&) - { - type_ = "mssql::long_callback"; - } - - void member_image_type:: - traverse_nstring (member_info&) - { - type_ = "mssql::ucs2_char*"; - } - - void member_image_type:: - traverse_long_nstring (member_info&) - { - type_ = "mssql::long_callback"; - } - - void member_image_type:: - traverse_binary (member_info&) - { - type_ = "char*"; - } - - void member_image_type:: - traverse_long_binary (member_info&) - { - type_ = "mssql::long_callback"; - } - - void member_image_type:: - traverse_date (member_info&) - { - type_ = "mssql::date"; - } - - void member_image_type:: - traverse_time (member_info&) - { - type_ = "mssql::time"; - } - - void member_image_type:: - traverse_datetime (member_info&) - { - type_ = "mssql::datetime"; - } - - void member_image_type:: - traverse_datetimeoffset (member_info&) - { - type_ = "mssql::datetimeoffset"; - } - - void member_image_type:: - traverse_uniqueidentifier (member_info&) - { - type_ = "mssql::uniqueidentifier"; - } - - void member_image_type:: - traverse_rowversion (member_info&) - { - type_ = "unsigned char*"; - } - - entry member_image_type_; - - // - // member_database_type - // - - static const char* integer_database_id[] = - { - "mssql::id_bit", - "mssql::id_tinyint", - "mssql::id_smallint", - "mssql::id_int", - "mssql::id_bigint" - }; - - 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 (semantics::data_member& 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) - { - type_id_ = integer_database_id[mi.st->type - sql_type::BIT]; - } - - void member_database_type_id:: - traverse_decimal (member_info&) - { - type_id_ = "mssql::id_decimal"; - } - - void member_database_type_id:: - traverse_smallmoney (member_info&) - { - type_id_ = "mssql::id_smallmoney"; - } - - void member_database_type_id:: - traverse_money (member_info&) - { - type_id_ = "mssql::id_money"; - } - - void member_database_type_id:: - traverse_float4 (member_info&) - { - type_id_ = "mssql::id_float4"; - } - - void member_database_type_id:: - traverse_float8 (member_info&) - { - type_id_ = "mssql::id_float8"; - } - - void member_database_type_id:: - traverse_string (member_info&) - { - type_id_ = "mssql::id_string"; - } - - void member_database_type_id:: - traverse_long_string (member_info&) - { - type_id_ = "mssql::id_long_string"; - } - - void member_database_type_id:: - traverse_nstring (member_info&) - { - type_id_ = "mssql::id_nstring"; - } - - void member_database_type_id:: - traverse_long_nstring (member_info&) - { - type_id_ = "mssql::id_long_nstring"; - } - - void member_database_type_id:: - traverse_binary (member_info&) - { - type_id_ = "mssql::id_binary"; - } - - void member_database_type_id:: - traverse_long_binary (member_info&) - { - type_id_ = "mssql::id_long_binary"; - } - - void member_database_type_id:: - traverse_date (member_info&) - { - type_id_ = "mssql::id_date"; - } - - void member_database_type_id:: - traverse_time (member_info&) - { - type_id_ = "mssql::id_time"; - } - - void member_database_type_id:: - traverse_datetime (member_info&) - { - type_id_ = "mssql::id_datetime"; - } - - void member_database_type_id:: - traverse_datetimeoffset (member_info&) - { - type_id_ = "mssql::id_datetimeoffset"; - } - - void member_database_type_id:: - traverse_uniqueidentifier (member_info&) - { - type_id_ = "mssql::id_uniqueidentifier"; - } - - void member_database_type_id:: - traverse_rowversion (member_info&) - { - type_id_ = "mssql::id_rowversion"; - } - - 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); - } - - virtual void - column_ctor (string const& type, string const& name, string const& base) - { - os << name << " ("; - - if (multi_dynamic) - os << "odb::query_column< " << type << " >& qc," << endl; - - os << "const char* t," << endl - << "const char* c," << endl - << "const char* conv," << endl - << "unsigned short p = 0," << endl - << "unsigned short s = 0xFFFF)" << endl - << " : " << base << " (" << (multi_dynamic ? "qc, " : "") << - "t, c, conv, p, s)" - << "{" - << "}"; - } - - virtual void - column_ctor_args_extra (semantics::data_member& m) - { - // For some types we need to pass precision and scale. - // - sql_type const& st (parse_sql_type (column_type (), m)); - - switch (st.type) - { - case sql_type::DECIMAL: - { - os << ", " << st.prec << ", " << st.scale; - break; - } - case sql_type::FLOAT: - { - os << ", " << st.prec; - break; - } - case sql_type::CHAR: - case sql_type::VARCHAR: - { - os << ", " << st.prec; - break; - } - case sql_type::TEXT: - { - os << ", 0"; // Unlimited. - break; - } - case sql_type::NCHAR: - case sql_type::NVARCHAR: - { - os << ", " << st.prec; // In 2-byte characters. - break; - } - case sql_type::NTEXT: - { - os << ", 0"; // Unlimited. - break; - } - case sql_type::BINARY: - case sql_type::VARBINARY: - { - os << ", " << st.prec; - break; - } - case sql_type::IMAGE: - { - os << ", 0"; // Unlimited. - break; - } - // Date-time types. - // - case sql_type::TIME: - case sql_type::DATETIME2: - case sql_type::DATETIMEOFFSET: - { - os << ", 0, " << st.scale; // Fractional seconds (scale). - break; - } - case sql_type::DATETIME: - { - os << ", 0, 3"; - break; - } - case sql_type::SMALLDATETIME: - { - os << ", 0, 8"; - break; - } - default: - { - break; - } - } - } - - private: - member_database_type_id member_database_type_id_; - }; - entry query_columns_; - } -} diff --git a/odb/relational/mssql/common.hxx b/odb/relational/mssql/common.hxx deleted file mode 100644 index 42ea412..0000000 --- a/odb/relational/mssql/common.hxx +++ /dev/null @@ -1,293 +0,0 @@ -// file : odb/relational/mssql/common.hxx -// license : GNU GPL v3; see accompanying LICENSE file - -#ifndef ODB_RELATIONAL_MSSQL_COMMON_HXX -#define ODB_RELATIONAL_MSSQL_COMMON_HXX - -#include -#include - -namespace relational -{ - namespace mssql - { - 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 mssql 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_decimal (member_info&) - { - } - - virtual void - traverse_smallmoney (member_info&) - { - } - - virtual void - traverse_money (member_info&) - { - } - - virtual void - traverse_float4 (member_info&) - { - } - - virtual void - traverse_float8 (member_info&) - { - } - - virtual void - traverse_string (member_info&) - { - } - - virtual void - traverse_long_string (member_info&) - { - } - - virtual void - traverse_nstring (member_info&) - { - } - - virtual void - traverse_long_nstring (member_info&) - { - } - - virtual void - traverse_binary (member_info&) - { - } - - virtual void - traverse_long_binary (member_info&) - { - } - - virtual void - traverse_date (member_info&) - { - } - - virtual void - traverse_time (member_info&) - { - } - - virtual void - traverse_datetime (member_info&) - { - } - - virtual void - traverse_datetimeoffset (member_info&) - { - } - - virtual void - traverse_uniqueidentifier (member_info&) - { - } - - virtual void - traverse_rowversion (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_decimal (member_info&); - - virtual void - traverse_smallmoney (member_info&); - - virtual void - traverse_money (member_info&); - - virtual void - traverse_float4 (member_info&); - - virtual void - traverse_float8 (member_info&); - - virtual void - traverse_string (member_info&); - - virtual void - traverse_long_string (member_info&); - - virtual void - traverse_nstring (member_info&); - - virtual void - traverse_long_nstring (member_info&); - - virtual void - traverse_binary (member_info&); - - virtual void - traverse_long_binary (member_info&); - - virtual void - traverse_date (member_info&); - - virtual void - traverse_time (member_info&); - - virtual void - traverse_datetime (member_info&); - - virtual void - traverse_datetimeoffset (member_info&); - - virtual void - traverse_uniqueidentifier (member_info&); - - virtual void - traverse_rowversion (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 (semantics::data_member&); - - virtual void - traverse_composite (member_info&); - - virtual void - traverse_integer (member_info&); - - virtual void - traverse_decimal (member_info&); - - virtual void - traverse_smallmoney (member_info&); - - virtual void - traverse_money (member_info&); - - virtual void - traverse_float4 (member_info&); - - virtual void - traverse_float8 (member_info&); - - virtual void - traverse_string (member_info&); - - virtual void - traverse_long_string (member_info&); - - virtual void - traverse_nstring (member_info&); - - virtual void - traverse_long_nstring (member_info&); - - virtual void - traverse_binary (member_info&); - - virtual void - traverse_long_binary (member_info&); - - virtual void - traverse_date (member_info&); - - virtual void - traverse_time (member_info&); - - virtual void - traverse_datetime (member_info&); - - virtual void - traverse_datetimeoffset (member_info&); - - virtual void - traverse_uniqueidentifier (member_info&); - - virtual void - traverse_rowversion (member_info&); - - private: - string type_id_; - }; - - struct has_long_data: object_columns_base, context - { - has_long_data (bool& r): r_ (r) {} - - virtual void - traverse_pointer (semantics::data_member& m, semantics::class_& c) - { - if (!inverse (m, key_prefix_)) - object_columns_base::traverse_pointer (m, c); - } - - virtual bool - traverse_column (semantics::data_member& m, string const&, bool) - { - if (long_data (parse_sql_type (column_type (), m))) - r_ = true; - - return true; - } - - private: - bool& r_; - }; - } -} -#endif // ODB_RELATIONAL_MSSQL_COMMON_HXX diff --git a/odb/relational/mssql/context.cxx b/odb/relational/mssql/context.cxx deleted file mode 100644 index afe1aa5..0000000 --- a/odb/relational/mssql/context.cxx +++ /dev/null @@ -1,766 +0,0 @@ -// file : odb/relational/mssql/context.cxx -// license : GNU GPL v3; see accompanying LICENSE file - -#include -#include - -#include -#include - -#include - -using namespace std; - -namespace relational -{ - namespace mssql - { - 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", "BIT", 0, false}, - - {"char", "CHAR(1)", 0, false}, - {"wchar_t", "NCHAR(1)", 0, false}, - {"signed char", "TINYINT", 0, false}, - {"unsigned char", "TINYINT", 0, false}, - - {"short int", "SMALLINT", 0, false}, - {"short unsigned int", "SMALLINT", 0, false}, - - {"int", "INT", 0, false}, - {"unsigned int", "INT", 0, false}, - - {"long int", "BIGINT", 0, false}, - {"long unsigned int", "BIGINT", 0, false}, - - {"long long int", "BIGINT", 0, false}, - {"long long unsigned int", "BIGINT", 0, false}, - - {"float", "REAL", 0, false}, - {"double", "FLOAT", 0, false}, - - {"::std::string", "VARCHAR(512)", "VARCHAR(256)", false}, - {"::std::wstring", "NVARCHAR(512)", "NVARCHAR(256)", false}, - - {"::size_t", "BIGINT", 0, false}, - {"::std::size_t", "BIGINT", 0, false}, - - // Windows GUID/UUID (typedef struct _GUID {...} GUID, UUID;). - // - {"::_GUID", "UNIQUEIDENTIFIER", 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 = false; - need_alias_as = true; - insert_send_auto_id = false; - delay_freeing_statement_result = true; - need_image_clone = true; - generate_bulk = true; - global_index = false; - global_fkey = true; - data_->bind_vector_ = "mssql::bind*"; - - // 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 128 limit. - // - if (i->size () > 128) - { - cerr << "warning: SQL name '" << *i << "' is longer than the " - << "SQL Server name limit of 128 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, 128); // Max identifier length is 128. - r += ']'; - } - - return r; - } - - string context:: - database_type_impl (semantics::type& t, - semantics::names* hint, - bool id, - bool* null) - { - string r (base_context::database_type_impl (t, hint, id, null)); - - if (!r.empty ()) - return r; - - using semantics::array; - - // char[N] mapping. - // - if (array* a = dynamic_cast (&t)) - { - semantics::type& bt (a->base_type ()); - bool c (bt.is_a ()); - - if (c || bt.is_a ()) - { - unsigned long long n (a->size ()); - - if (n == 0) - return r; - if (n == 1) - r = c ? "CHAR(" : "NCHAR("; - else - { - r = c ? "VARCHAR(" : "NVARCHAR("; - n--; - } - - if (n > (c ? 8000 : 4000)) - r += "max)"; - else - { - ostringstream ostr; - ostr << n; - r += ostr.str (); - r += ')'; - } - } - } - - return r; - } - - bool context:: - long_data (sql_type const& st) - { - bool r (false); - - // The same test as in common.cxx:traverse_simple(). - // - switch (st.type) - { - case sql_type::CHAR: - case sql_type::VARCHAR: - case sql_type::BINARY: - case sql_type::VARBINARY: - { - // Zero precision means max in VARCHAR(max). - // - if (st.prec == 0 || st.prec > options.mssql_short_limit ()) - r = true; - - break; - } - case sql_type::NCHAR: - case sql_type::NVARCHAR: - { - // Zero precision means max in NVARCHAR(max). Note that - // the precision is in 2-byte UCS-2 characters, not bytes. - // - if (st.prec == 0 || st.prec * 2 > options.mssql_short_limit ()) - r = true; - - break; - } - case sql_type::TEXT: - case sql_type::NTEXT: - case sql_type::IMAGE: - { - r = true; - break; - } - default: - break; - } - - return r; - } - - // - // SQL type parsing. - // - - namespace - { - struct sql_parser - { - typedef context::invalid_sql_type invalid_sql_type; - - sql_parser (custom_db_types const* ct): ct_ (ct) {} - - sql_type - parse (std::string sql) - { - r_ = sql_type (); - m_.clear (); - - // 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 (sql)) - { - r_.to = t.type.replace (sql, t.to); - r_.from = t.type.replace (sql, t.from); - sql = t.type.replace (sql, t.as); - break; - } - } - } - - l_.lex (sql); - - bool ok (true); - - try - { - ok = parse_name (); - } - catch (sql_lexer::invalid_input const& e) - { - ok = false; - m_ = "invalid SQL Server type declaration: " + e.message; - } - - if (!ok) - { - if (ct_ == 0) - return sql_type (); - else - throw invalid_sql_type (m_); - } - - return r_; - } - - bool - parse_name () - { - sql_token t (l_.next ()); - - if (t.type () != sql_token::t_identifier) - { - m_ = "expected SQL Server type name instead of '" + - t.string () + "'"; - return false; - } - - string id (upcase (t.identifier ())); - - if (id == "BIT") - { - r_.type = sql_type::BIT; - } - else if (id == "TINYINT") - { - r_.type = sql_type::TINYINT; - } - else if (id == "SMALLINT") - { - r_.type = sql_type::SMALLINT; - } - else if (id == "INT" || - id == "INTEGER") - { - r_.type = sql_type::INT; - } - else if (id == "BIGINT") - { - r_.type = sql_type::BIGINT; - } - else if (id == "DECIMAL" || - id == "NUMERIC" || - id == "DEC") - { - r_.type = sql_type::DECIMAL; - - r_.has_prec = true; - r_.prec = 18; - - r_.has_scale = true; - r_.scale = 0; - - if (!parse_precision (l_.next ())) - return false; - } - else if (id == "SMALLMONEY") - { - r_.type = sql_type::SMALLMONEY; - } - else if (id == "MONEY") - { - r_.type = sql_type::MONEY; - } - else if (id == "REAL") - { - r_.type = sql_type::FLOAT; - - r_.has_prec = true; - r_.prec = 24; - } - else if (id == "FLOAT") - { - r_.type = sql_type::FLOAT; - - r_.has_prec = true; - r_.prec = 53; - - if (!parse_precision (l_.next ())) - return false; - } - else if (id == "DOUBLE") - { - t = l_.next (); - - if (t.type () != sql_token::t_identifier || - upcase (t.identifier ()) != "PRECISION") - { - m_ = "expected 'PRECISION' instead of '" + t.string () + "'"; - return false; - } - - r_.type = sql_type::FLOAT; - - r_.has_prec = true; - r_.prec = 53; - - // It appears that DOUBLE PRECISION can be followed by the - // precision specification. - // - if (!parse_precision (l_.next ())) - return false; - } - else if (id == "CHAR" || - id == "CHARACTER") - { - if (!parse_char_trailer (false)) - return false; - } - else if (id == "VARCHAR") - { - r_.type = sql_type::VARCHAR; - - r_.has_prec = true; - r_.prec = 1; - - if (!parse_precision (l_.next ())) - return false; - } - else if (id == "TEXT") - { - r_.type = sql_type::TEXT; - r_.has_prec = true; - r_.prec = 0; - } - else if (id == "NCHAR") - { - r_.type = sql_type::NCHAR; - - r_.has_prec = true; - r_.prec = 1; - - if (!parse_precision (l_.next ())) - return false; - } - else if (id == "NVARCHAR") - { - r_.type = sql_type::NVARCHAR; - - r_.has_prec = true; - r_.prec = 1; - - if (!parse_precision (l_.next ())) - return false; - } - else if (id == "NTEXT") - { - r_.type = sql_type::NTEXT; - r_.has_prec = true; - r_.prec = 0; - } - else if (id == "NATIONAL") - { - t = l_.next (); - - if (t.type () == sql_token::t_identifier) - id = upcase (t.identifier ()); - - if (id == "TEXT") - { - r_.type = sql_type::NTEXT; - r_.has_prec = true; - r_.prec = 0; - } - else if (id == "CHAR" || - id == "CHARACTER") - { - if (!parse_char_trailer (true)) - return false; - } - else - { - m_ = "expected 'CHAR', 'CHARACTER', or 'TEXT' instead of '" - + t.string () + "'"; - return false; - } - } - else if (id == "BINARY") - { - // Can be just BINARY or BINARY VARYING. - // - t = l_.next (); - - if (t.type () == sql_token::t_identifier) - id = upcase (t.identifier ()); - - if (id == "VARYING") - { - r_.type = sql_type::VARBINARY; - t = l_.next (); - } - else - r_.type = sql_type::BINARY; - - r_.has_prec = true; - r_.prec = 1; - - if (!parse_precision (t)) - return false; - } - else if (id == "VARBINARY") - { - r_.type = sql_type::VARBINARY; - - r_.has_prec = true; - r_.prec = 1; - - if (!parse_precision (l_.next ())) - return false; - } - else if (id == "IMAGE") - { - r_.type = sql_type::IMAGE; - r_.has_prec = true; - r_.prec = 0; - } - else if (id == "DATE") - { - r_.type = sql_type::DATE; - } - else if (id == "TIME") - { - r_.type = sql_type::TIME; - - r_.has_scale = true; - r_.scale = 7; - - if (!parse_precision (l_.next ())) - return false; - } - else if (id == "DATETIME") - { - r_.type = sql_type::DATETIME; - } - else if (id == "DATETIME2") - { - r_.type = sql_type::DATETIME2; - - r_.has_scale = true; - r_.scale = 7; - - if (!parse_precision (l_.next ())) - return false; - } - else if (id == "SMALLDATETIME") - { - r_.type = sql_type::SMALLDATETIME; - } - else if (id == "DATETIMEOFFSET") - { - r_.type = sql_type::DATETIMEOFFSET; - - r_.has_scale = true; - r_.scale = 7; - - if (!parse_precision (l_.next ())) - return false; - } - else if (id == "UNIQUEIDENTIFIER") - { - r_.type = sql_type::UNIQUEIDENTIFIER; - } - else if (id == "ROWVERSION" || - id == "TIMESTAMP") - { - r_.type = sql_type::ROWVERSION; - } - else - { - m_ = "unexpected SQL Server type name '" + t.identifier () + "'"; - return false; - } - - return true; - } - - bool - parse_precision (sql_token t) - { - if (t.punctuation () == sql_token::p_lparen) - { - // Parse the precision. - // - t = l_.next (); - - if (t.type () == sql_token::t_identifier && - upcase (t.identifier ()) == "MAX") - { - r_.prec = 0; - r_.has_prec = true; - } - else if (t.type () == sql_token::t_int_lit) - { - unsigned short v; - istringstream is (t.literal ()); - - if (!(is >> v && is.eof ())) - { - m_ = "invalid precision value '" + t.literal () + "' in SQL " - "Server type declaration"; - return false; - } - - switch (r_.type) - { - case sql_type::TIME: - case sql_type::DATETIME2: - case sql_type::DATETIMEOFFSET: - { - r_.scale = v; - r_.has_scale = true; - break; - } - default: - { - r_.prec = v; - r_.has_prec = true; - break; - } - } - } - else - { - m_ = "integer precision expected in SQL Server type declaration"; - return false; - } - - // Parse the scale if present. - // - t = l_.next (); - - if (t.punctuation () == sql_token::p_comma) - { - // Scale can only be specified for the DECIMAL type. - // - if (r_.type != sql_type::DECIMAL) - { - m_ = "unexpected scale in SQL Server type declaration"; - return false; - } - - t = l_.next (); - - if (t.type () != sql_token::t_int_lit) - { - m_ = "integer scale expected in SQL Server type declaration"; - return false; - } - - istringstream is (t.literal ()); - - if (!(is >> r_.scale && is.eof ())) - { - m_ = "invalid scale value '" + t.literal () + "' in SQL " - "Server type declaration"; - return false; - } - - r_.has_scale = true; - t = l_.next (); - } - - if (t.punctuation () != sql_token::p_rparen) - { - m_ = "expected ')' in SQL Server type declaration"; - return false; - } - } - - return true; - } - - bool - parse_char_trailer (bool nat) - { - sql_token t (l_.next ()); - - string id; - - if (t.type () == sql_token::t_identifier) - id = upcase (t.identifier ()); - - if (id == "VARYING") - { - r_.type = nat ? sql_type::NVARCHAR : sql_type::VARCHAR; - t = l_.next (); - } - else - r_.type = nat ? sql_type::NCHAR : sql_type::CHAR; - - r_.has_prec = true; - r_.prec = 1; - - return parse_precision (t); - } - - private: - string - upcase (string const& s) - { - return context::upcase (s); - } - - private: - custom_db_types const* ct_; - sql_lexer l_; - sql_type r_; - string m_; // Error message. - }; - } - - 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 (); - } - } - } - - sql_type context:: - parse_sql_type (string const& sqlt, custom_db_types const* ct) - { - sql_parser p (ct); - return p.parse (sqlt); - } - } -} diff --git a/odb/relational/mssql/context.hxx b/odb/relational/mssql/context.hxx deleted file mode 100644 index 7701aaa..0000000 --- a/odb/relational/mssql/context.hxx +++ /dev/null @@ -1,194 +0,0 @@ -// file : odb/relational/mssql/context.hxx -// license : GNU GPL v3; see accompanying LICENSE file - -#ifndef ODB_RELATIONAL_MSSQL_CONTEXT_HXX -#define ODB_RELATIONAL_MSSQL_CONTEXT_HXX - -#include - -#include - -namespace relational -{ - namespace mssql - { - struct sql_type - { - // Keep the order in each block of types. - // - enum core_type - { - // Integral types. - // - BIT, - TINYINT, - SMALLINT, - INT, - BIGINT, - - // Fixed and floating point types. - // - DECIMAL, - SMALLMONEY, - MONEY, - FLOAT, - - // String and binary types. - // - CHAR, - VARCHAR, - TEXT, - - NCHAR, - NVARCHAR, - NTEXT, - - BINARY, - VARBINARY, - IMAGE, - - // Date-time types. - // - DATE, - TIME, - DATETIME, - DATETIME2, - SMALLDATETIME, - DATETIMEOFFSET, - - // Other types. - // - UNIQUEIDENTIFIER, - ROWVERSION, - - // Invalid type. - // - invalid - }; - - sql_type () : - type (invalid), - has_prec (false), prec (0), - has_scale (false), scale (0) - { - } - - core_type type; - - bool has_prec; - unsigned short prec; // Max numeric value is 8000. 0 indicates - // 'max' as in VARCHAR(max). - bool has_scale; - unsigned short scale; // Max value is 38. - - // 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); - - // Return true if this type is long data. - // - bool - long_data (sql_type const&); - - 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 const&, custom_db_types const* = 0); - - protected: - virtual string const& - convert_expr (string const&, semantics::data_member&, bool); - - 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_MSSQL_CONTEXT_HXX diff --git a/odb/relational/mssql/header.cxx b/odb/relational/mssql/header.cxx deleted file mode 100644 index ebdc734..0000000 --- a/odb/relational/mssql/header.cxx +++ /dev/null @@ -1,312 +0,0 @@ -// file : odb/relational/mssql/header.cxx -// license : GNU GPL v3; see accompanying LICENSE file - -#include - -#include -#include - -namespace relational -{ - namespace mssql - { - namespace header - { - namespace relational = relational::header; - - struct class1: relational::class1, context - { - class1 (base const& x): base (x) {} - - virtual void - object_public_extra_pre (type& c) - { - bool abst (abstract (c)); - - type* poly_root (polymorphic (c)); - bool poly (poly_root != 0); - bool poly_derived (poly && poly_root != &c); - - if (poly_derived || (abst && !poly)) - return; - - // Bulk operations batch size. - // - { - unsigned long long b (c.count ("bulk") - ? c.get ("bulk") - : 1); - - os << "static const std::size_t batch = " << b << "UL;" - << endl; - } - - // rowvesion - // - bool rv (false); - if (semantics::data_member* m = optimistic (c)) - { - sql_type t (parse_sql_type (column_type (*m), *m)); - rv = (t.type == sql_type::ROWVERSION); - } - - os << "static const bool rowversion = " << rv << ";" - << endl; - - // Disable bulk update if we have ROWVERSION since we don't - // yet support batch extraction of the version. - // - if (rv && c.count ("bulk-update")) - c.remove ("bulk-update"); - } - - virtual void - object_public_extra_post (type& c) - { - bool abst (abstract (c)); - - type* poly_root (polymorphic (c)); - bool poly (poly_root != 0); - bool poly_derived (poly && poly_root != &c); - - if (poly_derived || (abst && !poly)) - return; - - if (semantics::data_member* m = optimistic (c)) - { - sql_type t (parse_sql_type (column_type (*m), *m)); - if (t.type == sql_type::ROWVERSION) - { - os << "static version_type" << endl - << "version (const id_image_type&);" - << endl; - } - } - } - }; - entry class1_entry_; - - struct section_traits: relational::section_traits, context - { - section_traits (base const& x): base (x) {} - - virtual void - section_public_extra_pre (user_section&) - { - if (abstract (c_) && !polymorphic (c_)) - return; - - // rowvesion - // - bool rv (false); - if (semantics::data_member* m = optimistic (c_)) - { - sql_type t (parse_sql_type (column_type (*m), *m)); - rv = (t.type == sql_type::ROWVERSION); - } - - os << "static const bool rowversion = " << rv << ";" - << endl; - } - }; - entry section_traits_; - - struct image_type: relational::image_type, context - { - image_type (base const& x): base (x) {}; - - virtual void - image_extra (type& c) - { - if (!(composite (c) || (abstract (c) && !polymorphic (c)))) - { - type* poly_root (polymorphic (c)); - - // If this is a polymorphic type, only add callback to the root. - // - if (poly_root == 0 || poly_root == &c) - { - bool gc (options.generate_query ()); - - if (gc) - os << "mssql::change_callback change_callback_;" - << endl; - - os << "mssql::change_callback*" << endl - << "change_callback ()" - << "{"; - - if (gc) - os << "return &change_callback_;"; - else - os << "return 0;"; - - os << "}"; - } - } - } - }; - entry image_type_; - - 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;" - << "SQLLEN " << mi.var << "size_ind;" - << endl; - } - - virtual void - traverse_decimal (member_info& mi) - { - os << image_type << " " << mi.var << "value;" - << "SQLLEN " << mi.var << "size_ind;" - << endl; - } - - virtual void - traverse_smallmoney (member_info& mi) - { - os << image_type << " " << mi.var << "value;" - << "SQLLEN " << mi.var << "size_ind;" - << endl; - } - - virtual void - traverse_money (member_info& mi) - { - os << image_type << " " << mi.var << "value;" - << "SQLLEN " << mi.var << "size_ind;" - << endl; - } - - virtual void - traverse_float4 (member_info& mi) - { - os << image_type << " " << mi.var << "value;" - << "SQLLEN " << mi.var << "size_ind;" - << endl; - } - - virtual void - traverse_float8 (member_info& mi) - { - os << image_type << " " << mi.var << "value;" - << "SQLLEN " << mi.var << "size_ind;" - << endl; - } - - virtual void - traverse_string (member_info& mi) - { - // Extra character for the null-terminator that ODBC always adds. - // - os << "char " << mi.var << "value[" << mi.st->prec + 1 << "];" - << "SQLLEN " << mi.var << "size_ind;" - << endl; - } - - virtual void - traverse_long_string (member_info& mi) - { - os << "mutable " << image_type << " " << mi.var << "callback;" - << "SQLLEN " << mi.var << "size_ind;" - << endl; - } - - virtual void - traverse_nstring (member_info& mi) - { - // Extra character for the null-terminator that ODBC always adds. - // - os << "mssql::ucs2_char " << mi.var << "value[" << - mi.st->prec + 1 << "];" - << "SQLLEN " << mi.var << "size_ind;" - << endl; - } - - virtual void - traverse_long_nstring (member_info& mi) - { - os << "mutable " << image_type << " " << mi.var << "callback;" - << "SQLLEN " << mi.var << "size_ind;" - << endl; - } - - virtual void - traverse_binary (member_info& mi) - { - os << "char " << mi.var << "value[" << mi.st->prec << "];" - << "SQLLEN " << mi.var << "size_ind;" - << endl; - } - - virtual void - traverse_long_binary (member_info& mi) - { - os << "mutable " << image_type << " " << mi.var << "callback;" - << "SQLLEN " << mi.var << "size_ind;" - << endl; - } - - virtual void - traverse_date (member_info& mi) - { - os << image_type << " " << mi.var << "value;" - << "SQLLEN " << mi.var << "size_ind;" - << endl; - } - - virtual void - traverse_time (member_info& mi) - { - os << image_type << " " << mi.var << "value;" - << "SQLLEN " << mi.var << "size_ind;" - << endl; - } - - virtual void - traverse_datetime (member_info& mi) - { - os << image_type << " " << mi.var << "value;" - << "SQLLEN " << mi.var << "size_ind;" - << endl; - } - - virtual void - traverse_datetimeoffset (member_info& mi) - { - os << image_type << " " << mi.var << "value;" - << "SQLLEN " << mi.var << "size_ind;" - << endl; - } - - virtual void - traverse_uniqueidentifier (member_info& mi) - { - os << image_type << " " << mi.var << "value;" - << "SQLLEN " << mi.var << "size_ind;" - << endl; - } - - virtual void - traverse_rowversion (member_info& mi) - { - os << "unsigned char " << mi.var << "value[8];" - << "SQLLEN " << mi.var << "size_ind;" - << endl; - } - }; - entry image_member_; - } - } -} diff --git a/odb/relational/mssql/inline.cxx b/odb/relational/mssql/inline.cxx deleted file mode 100644 index eb581d6..0000000 --- a/odb/relational/mssql/inline.cxx +++ /dev/null @@ -1,42 +0,0 @@ -// file : odb/relational/mssql/inline.cxx -// license : GNU GPL v3; see accompanying LICENSE file - -#include - -#include -#include - -using namespace std; - -namespace relational -{ - namespace mssql - { - 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 << "size_ind == SQL_NULL_DATA;"; - else - os << "i." << mi.var << "size_ind = SQL_NULL_DATA;"; - } - }; - entry null_member_; - } - } -} diff --git a/odb/relational/mssql/model.cxx b/odb/relational/mssql/model.cxx deleted file mode 100644 index 0f5a85c..0000000 --- a/odb/relational/mssql/model.cxx +++ /dev/null @@ -1,66 +0,0 @@ -// file : odb/relational/mssql/model.cxx -// license : GNU GPL v3; see accompanying LICENSE file - -#include - -#include - -#include -#include - -using namespace std; - -namespace relational -{ - namespace mssql - { - namespace model - { - namespace relational = relational::model; - - struct object_columns: relational::object_columns, context - { - object_columns (base const& x): base (x) {} - - virtual string - default_enum (semantics::data_member& m, tree en, string const&) - { - // Make sure the column is mapped to an integer or DECIMAL type. - // - switch (parse_sql_type (column_type (), m, false).type) - { - case sql_type::BIT: - case sql_type::TINYINT: - case sql_type::SMALLINT: - case sql_type::INT: - case sql_type::BIGINT: - case sql_type::DECIMAL: - break; - default: - { - cerr << m.file () << ":" << m.line () << ":" << m.column () - << ": error: column with default value specified as C++ " - << "enumerator must map to SQL Server integer type" << endl; - - throw operation_failed (); - } - } - - using semantics::enumerator; - - enumerator& e (dynamic_cast (*unit.find (en))); - - ostringstream ostr; - - if (e.enum_ ().unsigned_ ()) - ostr << e.value (); - else - ostr << static_cast (e.value ()); - - return ostr.str (); - } - }; - entry object_columns_; - } - } -} diff --git a/odb/relational/mssql/schema.cxx b/odb/relational/mssql/schema.cxx deleted file mode 100644 index c5f6bc1..0000000 --- a/odb/relational/mssql/schema.cxx +++ /dev/null @@ -1,651 +0,0 @@ -// file : odb/relational/mssql/schema.cxx -// license : GNU GPL v3; see accompanying LICENSE file - -#include - -#include -#include - -using namespace std; - -namespace relational -{ - namespace mssql - { - namespace schema - { - namespace relational = relational::schema; - using relational::table_set; - - struct sql_emitter: relational::sql_emitter - { - sql_emitter (const base& x): base (x) {} - - virtual void - post () - { - if (!first_) // Ignore empty statements. - { - os << ';' << endl - << "GO" << endl - << endl; - } - } - }; - entry sql_emitter_; - - // - // File. - // - - struct sql_file: relational::sql_file, context - { - sql_file (const base& x): base (x) {} - - virtual void - prologue () - { - // Suppress the (x rows affected) messages from sqlcmd for DML - // statements. We only use DML for schema version management. - // - if ((model == 0 || model->version () != 0) && - !options.suppress_schema_version ()) - os << "SET NOCOUNT ON;" << endl - << endl; - } - }; - entry sql_file_; - - // - // Drop. - // - - struct drop_column: relational::drop_column, context - { - drop_column (base const& x): base (x) {} - - virtual void - traverse (sema_rel::drop_column& dc) - { - if (first_) - first_ = false; - else - os << "," << endl - << " "; - - os << quote_id (dc.name ()); - } - }; - entry drop_column_; - - 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) - { - bool migration (dropped_ == 0); - - if (migration) - { - if (fk.not_deferrable ()) - pre_statement (); - else - { - if (format_ != schema_format::sql) - return; - - os << "/*" << endl; - } - } - else - { - // Here we drop potentially deferrable keys and also need to - // test if the key exists. - // - pre_statement (); - - os << "IF OBJECT_ID(" << quote_string (fk.name ()) << ", " << - quote_string ("F") << ") IS NOT NULL" << endl - << " "; - } - - os << "ALTER TABLE " << quote_id (t.name ()) << endl - << (migration ? " " : " ") << "DROP CONSTRAINT " << - quote_id (fk.name ()) << endl; - - - if (!migration || fk.not_deferrable ()) - post_statement (); - else - os << "*/" << endl - << endl; - } - - 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)); - - bool c (!fk.not_deferrable () && !in_comment); - - if (c && format_ != schema_format::sql) - return; - - if (!first_) - os << (c ? "" : ",") << endl - << " "; - - if (c) - os << "/* "; - - os << quote_id (fk.name ()); - - if (c) - os << " */"; - - if (first_) - { - if (c) - // There has to be a real name otherwise the whole statement - // would have been commented out. - // - os << endl - << " "; - else - first_ = false; - } - } - }; - 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_; - - struct drop_table: relational::drop_table, context - { - drop_table (base const& x): base (x) {} - - virtual void - drop (sema_rel::table& t, bool migration) - { - // SQL Server has no IF EXISTS conditional for dropping tables. - // The following approach appears to be the recommended way to - // drop a table if it exists. - // - sema_rel::qname const& name (t.name ()); - - pre_statement (); - - if (!migration) - os << "IF OBJECT_ID(" << quote_string (name.string ()) << - ", " << quote_string ("U") << ") IS NOT NULL" << endl - << " "; - - os << "DROP TABLE " << quote_id (name) << endl; - - post_statement (); - } - }; - entry drop_table_; - - // - // Create. - // - - struct create_column: relational::create_column, context - { - create_column (base const& x): base (x) {} - - virtual void - traverse (sema_rel::add_column& ac) - { - if (first_) - first_ = false; - else - os << "," << endl - << " "; - - create (ac); - } - - virtual void - auto_ (sema_rel::primary_key&) - { - os << " IDENTITY"; - } - }; - 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 SQL Server 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) - { - // SQL Server 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) - { - bool c (!fk.not_deferrable () && !in_comment); - - if (c) - diagnose (fk); - - if (c && format_ != schema_format::sql) - return; - - if (!first_) - os << (c ? "" : ",") << endl - << " "; - - if (c) - os << "/*" << endl - << " "; - - os << "CONSTRAINT "; - create (fk); - - if (c) - os << endl - << " */"; - - if (first_) - { - if (c) - // There has to be a real key otherwise the whole statement - // would have been commented out. - // - os << endl - << " "; - else - first_ = false; - } - } - - virtual void - deferrable (sema_rel::deferrable) - { - // This will still be called to output the comment. - } - }; - entry create_foreign_key_; - - 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 ("mssql-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 ()) << endl - << " ADD "; - - 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 - traverse (sema_rel::column& c) - { - // Relax (NULL) in pre and tighten (NOT NULL) in post. - // - if (pre_ != c.null ()) - return; - - using sema_rel::table; - table& at (static_cast (c.scope ())); - - pre_statement (); - - os << "ALTER TABLE " << quote_id (at.name ()) << endl - << " ALTER COLUMN "; - alter (c); - os << endl; - - post_statement (); - } - }; - 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) - { - 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) - { - // SQL Server can only alter one kind of thing at a time. - // - if (check (at)) - { - bool deferrable (check_drop_deferrable_only (at)); - - if (!deferrable || format_ == schema_format::sql) - { - if (deferrable) - { - os << "/*" << endl; - in_comment = true; - } - else - pre_statement (); - - os << "ALTER TABLE " << quote_id (at.name ()) << endl - << " DROP CONSTRAINT "; - - instance dfc (*this); - trav_rel::unames n (*dfc); - names (at, n); - os << endl; - - if (deferrable) - { - in_comment = false; - os << "*/" << endl - << endl; - } - else - post_statement (); - } - } - - if (check (at)) - { - pre_statement (); - - os << "ALTER TABLE " << quote_id (at.name ()) << endl - << " ADD "; - - instance cc (*this); - trav_rel::unames n (*cc); - names (at, n); - os << endl; - - post_statement (); - } - - // For ALTER COLUMN, SQL Server can only have one per ALTER TABLE. - // - { - bool tl (true); // (Im)perfect forwarding. - instance ac (*this, tl); - trav_rel::unames n (*ac); - names (at, n); - } - } - }; - 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) - { - 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) - { - // SQL Server can only alter one kind of thing at a time. - // - if (check (at)) - { - pre_statement (); - - os << "ALTER TABLE " << quote_id (at.name ()) << endl - << " DROP COLUMN "; - - instance dc (*this); - trav_rel::unames n (*dc); - names (at, n); - os << endl; - - post_statement (); - } - - // For ALTER COLUMN, SQL Server can only have one per ALTER TABLE. - // - { - bool fl (false); // (Im)perfect forwarding. - instance ac (*this, fl); - trav_rel::unames n (*ac); - names (at, n); - } - - if (check (at)) - { - bool deferrable (check_add_deferrable_only (at)); - - if (!deferrable || format_ == schema_format::sql) - { - if (deferrable) - { - os << "/*" << endl; - in_comment = true; - } - else - pre_statement (); - - os << "ALTER TABLE " << quote_id (at.name ()) << endl - << " ADD "; - - instance cfc (*this); - trav_rel::unames n (*cfc); - names (at, n); - os << endl; - - if (deferrable) - { - in_comment = false; - os << "*/" << endl - << endl; - } - else - post_statement (); - } - } - } - }; - 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 << "IF OBJECT_ID(" << quote_string (table_.string ()) << - ", " << quote_string ("U") << ") IS NULL" << endl - << " CREATE TABLE " << qt_ << " (" << endl - << " " << qn_ << " VARCHAR(256) NOT NULL PRIMARY KEY," << endl - << " " << qv_ << " BIGINT NOT NULL," << endl - << " " << qm_ << " BIT NOT NULL)" << endl; - - post_statement (); - } - - virtual void - create (sema_rel::version v) - { - pre_statement (); - - os << "IF NOT EXISTS (SELECT 1 FROM " << qt_ << " WHERE " << qn_ << - " = " << qs_ << ")" << endl - << " INSERT INTO " << qt_ << " (" << endl - << " " << qn_ << ", " << qv_ << ", " << qm_ << ")" << endl - << " VALUES (" << qs_ << ", " << v << ", 0)" << endl; - - post_statement (); - } - }; - entry version_table_; - } - } -} diff --git a/odb/relational/mssql/source.cxx b/odb/relational/mssql/source.cxx deleted file mode 100644 index 573104d..0000000 --- a/odb/relational/mssql/source.cxx +++ /dev/null @@ -1,1201 +0,0 @@ -// file : odb/relational/mssql/source.cxx -// license : GNU GPL v3; see accompanying LICENSE file - -#include - -#include -#include - -using namespace std; - -namespace relational -{ - namespace mssql - { - namespace source - { - namespace relational = relational::source; - - // - // - struct query_parameters: relational::query_parameters - { - query_parameters (base const& x): base (x) {} - - virtual string - auto_id (semantics::data_member&, const string&, const string&) - { - return ""; - } - }; - entry query_parameters_; - - // - // - struct object_columns: relational::object_columns, context - { - object_columns (base const& x) - : base (x), rowversion_ (false), column_count_ (0) {} - - virtual bool - column (semantics::data_member& m, - string const& table, - string const& column) - { - // Don't add a column for auto id in the INSERT statement. - // Only simple, direct id can be auto. - // - if (sk_ == statement_insert && key_prefix_.empty () && auto_ (m)) - return false; - - // Don't update the ROWVERSION column explicitly. - // - if (sk_ == statement_update) - { - sql_type t (parse_sql_type (column_type (), m)); - if (t.type == sql_type::ROWVERSION) - { - rowversion_ = true; - return false; - } - } - - bool r (base::column (m, table, column)); - - // Count the number of columns in the UPDATE statement, but - // excluding soft-deleted. - // - if (sk_ == statement_update && r && !deleted (member_path_)) - column_count_++; - - return r; - } - - virtual void - traverse_post (semantics::nameable& n) - { - if (rowversion_ && column_count_ == 0) - { - location l (n.location ()); - error (l) << "ROWVERSION in an object without any readwrite " - "data members" << endl; - error (l) << "UPDATE statement will be empty" << endl; - throw operation_failed (); - } - } - - private: - bool rowversion_; - size_t column_count_; - }; - entry object_columns_; - - // - // - struct persist_statement_params: relational::persist_statement_params, - context - { - persist_statement_params (base const& x): base (x) {} - - virtual string - version_value (semantics::data_member& m) - { - sql_type t (parse_sql_type (column_type (), m)); - return t.type == sql_type::ROWVERSION ? "DEFAULT" : "1"; - } - }; - entry persist_statement_params_; - - // - // bind - // - - static const char* integer_buffer_types[] = - { - "mssql::bind::bit", - "mssql::bind::tinyint", - "mssql::bind::smallint", - "mssql::bind::int_", - "mssql::bind::bigint" - }; - - 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) - { - os << b << ".type = " << - integer_buffer_types[mi.st->type - sql_type::BIT] << ";" - << b << ".buffer = &" << arg << "." << mi.var << "value;" - << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;"; - } - - virtual void - traverse_decimal (member_info& mi) - { - os << b << ".type = mssql::bind::decimal;" - << b << ".buffer = &" << arg << "." << mi.var << "value;" - << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;" - // Encode precision (p) and scale (s) as (p * 100 + s). - // - << b << ".capacity = " << mi.st->prec * 100 + mi.st->scale << ";"; - } - - virtual void - traverse_smallmoney (member_info& mi) - { - os << b << ".type = mssql::bind::smallmoney;" - << b << ".buffer = &" << arg << "." << mi.var << "value;" - << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;"; - } - - virtual void - traverse_money (member_info& mi) - { - os << b << ".type = mssql::bind::money;" - << b << ".buffer = &" << arg << "." << mi.var << "value;" - << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;"; - } - - virtual void - traverse_float4 (member_info& mi) - { - os << b << ".type = mssql::bind::float4;" - << b << ".buffer = &" << arg << "." << mi.var << "value;" - << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;" - << b << ".capacity = " << mi.st->prec << ";"; - } - - virtual void - traverse_float8 (member_info& mi) - { - os << b << ".type = mssql::bind::float8;" - << b << ".buffer = &" << arg << "." << mi.var << "value;" - << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;" - << b << ".capacity = " << mi.st->prec << ";"; - } - - virtual void - traverse_string (member_info& mi) - { - os << b << ".type = mssql::bind::string;" - << b << ".buffer = &" << arg << "." << mi.var << "value;" - << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;" - << b << ".capacity = static_cast (sizeof (" << - arg << "." << mi.var << "value));"; - } - - virtual void - traverse_long_string (member_info& mi) - { - os << b << ".type = mssql::bind::long_string;" - << b << ".buffer = &" << arg << "." << mi.var << "callback;" - << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;" - // Encode the column size with 0 indicating unlimited. - // - << b << ".capacity = " << mi.st->prec << ";"; - } - - virtual void - traverse_nstring (member_info& mi) - { - os << b << ".type = mssql::bind::nstring;" - << b << ".buffer = &" << arg << "." << mi.var << "value;" - << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;" - << b << ".capacity = static_cast (sizeof (" << - arg << "." << mi.var << "value));"; - } - - virtual void - traverse_long_nstring (member_info& mi) - { - os << b << ".type = mssql::bind::long_nstring;" - << b << ".buffer = &" << arg << "." << mi.var << "callback;" - << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;" - // Encode the column size (in bytes) with 0 indicating unlimited. - // - << b << ".capacity = " << mi.st->prec * 2 << ";"; - } - - virtual void - traverse_binary (member_info& mi) - { - os << b << ".type = mssql::bind::binary;" - << b << ".buffer = &" << arg << "." << mi.var << "value;" - << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;" - << b << ".capacity = static_cast (sizeof (" << - arg << "." << mi.var << "value));"; - } - - virtual void - traverse_long_binary (member_info& mi) - { - os << b << ".type = mssql::bind::long_binary;" - << b << ".buffer = &" << arg << "." << mi.var << "callback;" - << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;" - // Encode the column size with 0 indicating unlimited. - // - << b << ".capacity = " << mi.st->prec << ";"; - } - - virtual void - traverse_date (member_info& mi) - { - os << b << ".type = mssql::bind::date;" - << b << ".buffer = &" << arg << "." << mi.var << "value;" - << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;"; - } - - virtual void - traverse_time (member_info& mi) - { - os << b << ".type = mssql::bind::time;" - << b << ".buffer = &" << arg << "." << mi.var << "value;" - << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;" - // Encode fractional seconds (scale). - // - << b << ".capacity = " << mi.st->scale << ";"; - } - - virtual void - traverse_datetime (member_info& mi) - { - unsigned short scale (0); - - switch (mi.st->type) - { - case sql_type::DATETIME: - { - // Looks like it is 3 (rounded to 0.000, 0.003, or 0.007). - // - scale = 3; - break; - } - case sql_type::DATETIME2: - { - scale = mi.st->scale; - break; - } - case sql_type::SMALLDATETIME: - { - // No seconds in SMALLDATATIME. Encode it a special precision - // value (8). - // - scale = 8; - break; - } - default: - { - assert (false); - break; - } - } - - os << b << ".type = mssql::bind::datetime;" - << b << ".buffer = &" << arg << "." << mi.var << "value;" - << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;" - // Encode fractional seconds (scale). - // - << b << ".capacity = " << scale << ";"; - } - - virtual void - traverse_datetimeoffset (member_info& mi) - { - os << b << ".type = mssql::bind::datetimeoffset;" - << b << ".buffer = &" << arg << "." << mi.var << "value;" - << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;" - // Encode fractional seconds (scale). - // - << b << ".capacity = " << mi.st->scale << ";"; - } - - virtual void - traverse_uniqueidentifier (member_info& mi) - { - os << b << ".type = mssql::bind::uniqueidentifier;" - << b << ".buffer = &" << arg << "." << mi.var << "value;" - << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;"; - } - - virtual void - traverse_rowversion (member_info& mi) - { - os << b << ".type = mssql::bind::rowversion;" - << b << ".buffer = &" << arg << "." << mi.var << "value;" - << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;"; - } - }; - entry bind_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 << "size_ind = SQL_NULL_DATA;"; - } - - virtual void - check_accessor (member_info& mi, member_access& ma) - { - // We cannot use accessors that return by-value for long data - // members. - // - if (long_data (*mi.st) && ma.by_value) - { - error (ma.loc) << "accessor returning a value cannot be used " - << "for a data member of SQL Server long data " - << "type" << endl; - info (ma.loc) << "accessor returning a const reference is required" - << endl; - info (mi.m.location ()) << "data member is defined here" << endl; - throw operation_failed (); - } - } - - virtual void - traverse_integer (member_info& mi) - { - os << traits << "::set_image (" << endl - << "i." << mi.var << "value, is_null, " << member << ");" - << "i." << mi.var << "size_ind = is_null ? SQL_NULL_DATA : 0;"; - } - - virtual void - traverse_decimal (member_info& mi) - { - os << traits << "::set_image (" << endl - << "i." << mi.var << "value, is_null, " << member << ");" - << "i." << mi.var << "size_ind = is_null ? SQL_NULL_DATA : 0;"; - } - - virtual void - traverse_smallmoney (member_info& mi) - { - os << traits << "::set_image (" << endl - << "i." << mi.var << "value, is_null, " << member << ");" - << "i." << mi.var << "size_ind = is_null ? SQL_NULL_DATA : 4;"; - } - - virtual void - traverse_money (member_info& mi) - { - os << traits << "::set_image (" << endl - << "i." << mi.var << "value, is_null, " << member << ");" - << "i." << mi.var << "size_ind = is_null ? SQL_NULL_DATA : 8;"; - } - - virtual void - traverse_float4 (member_info& mi) - { - os << traits << "::set_image (" << endl - << "i." << mi.var << "value, is_null, " << member << ");" - << "i." << mi.var << "size_ind = is_null ? SQL_NULL_DATA : 0;"; - } - - virtual void - traverse_float8 (member_info& mi) - { - os << traits << "::set_image (" << endl - << "i." << mi.var << "value, is_null, " << member << ");" - << "i." << mi.var << "size_ind = is_null ? SQL_NULL_DATA : 0;"; - } - - virtual void - traverse_string (member_info& mi) - { - os << "std::size_t size (0);" - << traits << "::set_image (" << endl - << "i." << mi.var << "value," << endl - // Don't mention the extra character for the null-terminator. - << "sizeof (i." << mi.var << "value) - 1," << endl - << "size," << endl - << "is_null," << endl - << member << ");" - << "i." << mi.var << "size_ind =" << endl - << " is_null ? SQL_NULL_DATA : static_cast (size);"; - } - - virtual void - traverse_long_string (member_info& mi) - { - os << traits << "::set_image (" << endl - << "i." << mi.var << "callback.callback.param," << endl - << "i." << mi.var << "callback.context.param," << endl - << "is_null," << endl - << member << ");" - << "i." << mi.var << "size_ind = is_null ? " << - "SQL_NULL_DATA : SQL_DATA_AT_EXEC;"; - } - - virtual void - traverse_nstring (member_info& mi) - { - os << "std::size_t size (0);" - << traits << "::set_image (" << endl - << "i." << mi.var << "value," << endl - // Don't mention the extra character for the null-terminator. - << "sizeof (i." << mi.var << "value) / 2 - 1," << endl - << "size," << endl - << "is_null," << endl - << member << ");" - << "i." << mi.var << "size_ind =" << endl - << " is_null ? SQL_NULL_DATA : static_cast (size * 2);"; - } - - virtual void - traverse_long_nstring (member_info& mi) - { - os << traits << "::set_image (" << endl - << "i." << mi.var << "callback.callback.param," << endl - << "i." << mi.var << "callback.context.param," << endl - << "is_null," << endl - << member << ");" - << "i." << mi.var << "size_ind = is_null ? " << - "SQL_NULL_DATA : SQL_DATA_AT_EXEC;"; - } - - virtual void - traverse_binary (member_info& mi) - { - 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 << "size_ind =" << endl - << " is_null ? SQL_NULL_DATA : static_cast (size);"; - } - - virtual void - traverse_long_binary (member_info& mi) - { - os << traits << "::set_image (" << endl - << "i." << mi.var << "callback.callback.param," << endl - << "i." << mi.var << "callback.context.param," << endl - << "is_null," << endl - << member << ");" - << "i." << mi.var << "size_ind = is_null ? " << - "SQL_NULL_DATA : SQL_DATA_AT_EXEC;"; - } - - virtual void - traverse_date (member_info& mi) - { - os << traits << "::set_image (" << endl - << "i." << mi.var << "value, is_null, " << member << ");" - << "i." << mi.var << "size_ind = is_null ? SQL_NULL_DATA : 0;"; - } - - virtual void - traverse_time (member_info& mi) - { - os << traits << "::set_image (" << endl - << "i." << mi.var << "value, " << mi.st->scale << ", " << - "is_null, " << member << ");" - << "i." << mi.var << "size_ind = is_null" << endl - << " ? SQL_NULL_DATA" << endl - << " : static_cast (sizeof (i." << mi.var << "value));"; - } - - virtual void - traverse_datetime (member_info& mi) - { - // The same code as in bind. - // - unsigned short scale (0); - - switch (mi.st->type) - { - case sql_type::DATETIME: - { - scale = 3; - break; - } - case sql_type::DATETIME2: - { - scale = mi.st->scale; - break; - } - case sql_type::SMALLDATETIME: - { - scale = 8; - break; - } - default: - { - assert (false); - break; - } - } - - os << traits << "::set_image (" << endl - << "i." << mi.var << "value, " << scale << ", " << - "is_null, " << member << ");" - << "i." << mi.var << "size_ind = is_null ? SQL_NULL_DATA : 0;"; - } - - virtual void - traverse_datetimeoffset (member_info& mi) - { - os << traits << "::set_image (" << endl - << "i." << mi.var << "value, " << mi.st->scale << ", " << - "is_null, " << member << ");" - << "i." << mi.var << "size_ind = is_null" << endl - << " ? SQL_NULL_DATA" << endl - << " : static_cast (sizeof (i." << mi.var << "value));"; - } - - virtual void - traverse_uniqueidentifier (member_info& mi) - { - os << traits << "::set_image (" << endl - << "i." << mi.var << "value, is_null, " << member << ");" - << "i." << mi.var << "size_ind = is_null ? SQL_NULL_DATA : 0;"; - } - - virtual void - traverse_rowversion (member_info& mi) - { - os << traits << "::set_image (" << endl - << "i." << mi.var << "value, is_null, " << member << ");" - << "i." << mi.var << "size_ind = is_null ? SQL_NULL_DATA : 8;"; - } - }; - 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 << "size_ind == SQL_NULL_DATA"; - } - - virtual void - check_modifier (member_info& mi, member_access& ma) - { - // We cannot use by-value modifier for long data members. - // - if (long_data (*mi.st) && ma.placeholder ()) - { - error (ma.loc) << "modifier accepting a value cannot be used " - << "for a data member of SQL Server long data " - << "type" << endl; - info (ma.loc) << "modifier returning a non-const reference is " - << "required" << endl; - info (mi.m.location ()) << "data member is defined here" << endl; - throw operation_failed (); - } - } - - virtual void - traverse_integer (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "i." << mi.var << "size_ind == SQL_NULL_DATA);" - << endl; - } - - virtual void - traverse_decimal (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "i." << mi.var << "size_ind == SQL_NULL_DATA);" - << endl; - } - - virtual void - traverse_smallmoney (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "i." << mi.var << "size_ind == SQL_NULL_DATA);" - << endl; - } - - virtual void - traverse_money (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "i." << mi.var << "size_ind == SQL_NULL_DATA);" - << endl; - } - - virtual void - traverse_float4 (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "i." << mi.var << "size_ind == SQL_NULL_DATA);" - << endl; - } - - virtual void - traverse_float8 (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "i." << mi.var << "size_ind == SQL_NULL_DATA);" - << endl; - } - - virtual void - traverse_string (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "static_cast (i." << mi.var << "size_ind)," << endl - << "i." << mi.var << "size_ind == SQL_NULL_DATA);" - << endl; - } - - virtual void - traverse_long_string (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "callback.callback.result," << endl - << "i." << mi.var << "callback.context.result);" - << endl; - } - - virtual void - traverse_nstring (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "static_cast (" << - "i." << mi.var << "size_ind / 2)," << endl - << "i." << mi.var << "size_ind == SQL_NULL_DATA);" - << endl; - } - - virtual void - traverse_long_nstring (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "callback.callback.result," << endl - << "i." << mi.var << "callback.context.result);" - << endl; - } - - virtual void - traverse_binary (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "static_cast (i." << mi.var << "size_ind)," << endl - << "i." << mi.var << "size_ind == SQL_NULL_DATA);" - << endl; - } - - virtual void - traverse_long_binary (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "callback.callback.result," << endl - << "i." << mi.var << "callback.context.result);" - << endl; - } - - virtual void - traverse_date (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "i." << mi.var << "size_ind == SQL_NULL_DATA);" - << endl; - } - - virtual void - traverse_time (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "i." << mi.var << "size_ind == SQL_NULL_DATA);" - << endl; - } - - virtual void - traverse_datetime (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "i." << mi.var << "size_ind == SQL_NULL_DATA);" - << endl; - } - - virtual void - traverse_datetimeoffset (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "i." << mi.var << "size_ind == SQL_NULL_DATA);" - << endl; - } - - virtual void - traverse_uniqueidentifier (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "i." << mi.var << "size_ind == SQL_NULL_DATA);" - << endl; - } - - virtual void - traverse_rowversion (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "i." << mi.var << "size_ind == SQL_NULL_DATA);" - << endl; - } - }; - entry init_value_member_; - - struct statement_columns_common: context - { - void - process (relational::statement_columns& cols, - statement_kind sk, - bool dynamic) - { - using relational::statement_columns; - - // Long data columns must come last in the SELECT statement. If - // this statement is going to be processed at runtime, then this - // will be taken care of then. - // - if (sk != statement_select || dynamic) - return; - - // Go over the columns list while keeping track of how many - // columns we have examined. If the current column is long data, - // then move it to the back. Stop once we have examined all the - // columns. - // - size_t n (cols.size ()); - for (statement_columns::iterator i (cols.begin ()); n != 0; --n) - { - if (long_data (parse_sql_type (i->type, *i->member))) - { - cols.push_back (*i); - i = cols.erase (i); - } - else - ++i; - } - } - }; - - struct container_traits: relational::container_traits, - statement_columns_common - { - container_traits (base const& x): base (x) {} - - virtual void - cache_result (string const&) - { - // Caching is not necessary since with MARS enabled SQL Server - // can execute several interleaving statements. - // - } - - virtual void - init_value_extra () - { - os << "sts.select_statement ().stream_result ();" - << endl; - } - - virtual void - process_statement_columns (relational::statement_columns& cols, - statement_kind sk, - bool dynamic) - { - statement_columns_common::process (cols, sk, dynamic); - } - }; - entry container_traits_; - - struct section_traits: relational::section_traits, - statement_columns_common - { - section_traits (base const& x): base (x) {} - - virtual void - init_value_extra () - { - os << "st.stream_result ();"; - } - - virtual void - process_statement_columns (relational::statement_columns& cols, - statement_kind sk, - bool dynamic) - { - statement_columns_common::process (cols, sk, dynamic); - } - - virtual string - optimistic_version_increment (semantics::data_member& m) - { - sql_type t (parse_sql_type (column_type (m), m)); - return t.type != sql_type::ROWVERSION - ? "1" - : "version (sts.id_image ())"; - } - - virtual string - update_statement_extra (user_section&) - { - string r; - - semantics::data_member* ver (optimistic (c_)); - - if (ver == 0 || - parse_sql_type (column_type (*ver), *ver).type != - sql_type::ROWVERSION) - return r; - - // ROWVERSION & SQL Server 2005 incompatibility is detected - // in persist_statement_extra. - // - r = "OUTPUT INSERTED." + - convert_from (column_qname (*ver, column_prefix ()), *ver); - - return r; - } - }; - entry section_traits_; - - struct class_: relational::class_, statement_columns_common - { - class_ (base const& x): - base (x), init_version_value_member_id_image_ ("v", "version_") {} - - virtual void - init_image_pre (type& c) - { - if (options.generate_query () && - !(composite (c) || (abstract (c) && !polymorphic (c)))) - { - type* poly_root (polymorphic (c)); - bool poly_derived (poly_root != 0 && poly_root != &c); - - if (poly_derived) - os << "{" - << "root_traits::image_type& ri (root_image (i));" - << endl; - - string i (poly_derived ? "ri" : "i"); - - os << "if (" << i << ".change_callback_.callback != 0)" << endl - << "(" << i << ".change_callback_.callback) (" << - i << ".change_callback_.context);"; - - if (poly_derived) - os << "}"; - else - os << endl; - } - } - - virtual void - init_value_extra () - { - os << "st.stream_result ();"; - } - - virtual string - persist_statement_extra (type& c, - relational::query_parameters&, - persist_position p) - { - string r; - - type* poly_root (polymorphic (c)); - bool poly_derived (poly_root != 0 && poly_root != &c); - - // If we are a derived type in a polymorphic hierarchy, then - // auto id/version are handled by the root. - // - if (poly_derived) - return r; - - // See if we have auto id or ROWVERSION version. - // - data_member_path* id (id_member (c)); - semantics::data_member* ver (optimistic (c)); - - if (id != 0 && !auto_ (*id)) - id = 0; - - if (ver != 0) - { - sql_type t (parse_sql_type (column_type (*ver), *ver)); - if (t.type != sql_type::ROWVERSION) - ver = 0; - } - - if (id == 0 && ver == 0) - return r; - - // SQL Server 2005 has a bug that causes it to fail on an - // INSERT statement with the OUTPUT clause if data for one - // of the inserted columns is supplied at execution (long - // data). To work around this problem we use the less - // efficient batch of INSERT and SELECT statements. - // - if (options.mssql_server_version () <= mssql_version (9, 0)) - { - bool ld (false); - - if (c.count ("mssql-has-long-data")) - ld = c.get ("mssql-has-long-data"); - else - { - has_long_data t (ld); - t.traverse (c); - c.set ("mssql-has-long-data", ld); - } - - if (ld) - { - if (p == persist_after_values) - { - // SQL Server 2005 has no eqivalent of SCOPE_IDENTITY for - // ROWVERSION. - // - if (ver != 0) - { - error (c.location ()) << "in SQL Server 2005 ROWVERSION " << - "value cannot be retrieved for a persistent class " << - "containing long data" << endl; - throw operation_failed (); - } - - // We also cannot support bulk INSERT. - // - if (c.count ("bulk-persist")) - { - error (c.location ()) << "in SQL Server 2005 bulk " << - "persist operation cannot be implemented for a " << - "persistent class containing long data" << endl; - throw operation_failed (); - } - - r = "; SELECT " + - convert_from ("SCOPE_IDENTITY()", *id->back ()); - } - - return r; - } - } - - if (p == persist_after_columns) - { - r = "OUTPUT "; - - // Top-level auto id column. - // - if (id != 0) - r += "INSERTED." + - convert_from (column_qname (*id), *id->back ()); - - // Top-level version column. - // - if (ver != 0) - { - if (id != 0) - r += ','; - - r += "INSERTED." + convert_from ( - column_qname (*ver, column_prefix ()), *ver); - } - } - - return r; - } - - virtual string - update_statement_extra (type& c) - { - string r; - - type* poly_root (polymorphic (c)); - bool poly_derived (poly_root != 0 && poly_root != &c); - - // If we are a derived type in a polymorphic hierarchy, then - // version is handled by the root. - // - if (poly_derived) - return r; - - semantics::data_member* ver (optimistic (c)); - - if (ver == 0 || - parse_sql_type (column_type (*ver), *ver).type != - sql_type::ROWVERSION) - return r; - - // Long data & SQL Server 2005 incompatibility is detected - // in persist_statement_extra. - // - r = "OUTPUT INSERTED." + - convert_from (column_qname (*ver, column_prefix ()), *ver); - - return r; - } - - virtual void - process_statement_columns (relational::statement_columns& cols, - statement_kind sk, - bool dynamic) - { - statement_columns_common::process (cols, sk, dynamic); - } - - virtual string - optimistic_version_init (semantics::data_member& m, bool index) - { - sql_type t (parse_sql_type (column_type (m), m)); - return t.type != sql_type::ROWVERSION - ? "1" - : (index - ? "version (sts.id_image (i))" - : "version (sts.id_image ())"); - } - - virtual string - optimistic_version_increment (semantics::data_member& m, bool index) - { - sql_type t (parse_sql_type (column_type (m), m)); - return t.type != sql_type::ROWVERSION - ? "1" - : (index - ? "version (sts.id_image (i))" - : "version (sts.id_image ())"); - } - - virtual bool - optimistic_insert_bind_version (semantics::data_member& m) - { - sql_type t (parse_sql_type (column_type (m), m)); - return t.type == sql_type::ROWVERSION; - } - - virtual void - object_extra (type& c) - { - bool abst (abstract (c)); - - type* poly_root (polymorphic (c)); - bool poly (poly_root != 0); - bool poly_derived (poly && poly_root != &c); - - if (poly_derived || (abst && !poly)) - return; - - if (semantics::data_member* m = optimistic (c)) - { - sql_type t (parse_sql_type (column_type (*m), *m)); - if (t.type == sql_type::ROWVERSION) - { - string const& type (class_fq_name (c)); - string traits ("access::object_traits_impl< " + type + ", id_" + - db.string () + " >"); - - os << traits << "::version_type" << endl - << traits << "::" << endl - << "version (const id_image_type& i)" - << "{" - << "version_type v;"; - init_version_value_member_id_image_->traverse (*m); - os << "return v;" - << "}"; - } - } - } - - virtual string - from_trailer (type& c) - { - return c.get ("query").for_update - ? " WITH (UPDLOCK)" - : ""; - } - - virtual string - select_trailer (type&) {return "";} - - private: - // Go via the dynamic creation to get access to the constructor. - // - instance - init_version_value_member_id_image_; - }; - entry class_entry_; - } - } -} -- cgit v1.1