diff options
Diffstat (limited to 'odb/relational/oracle')
-rw-r--r-- | odb/relational/oracle/common.cxx | 522 | ||||
-rw-r--r-- | odb/relational/oracle/common.hxx | 203 | ||||
-rw-r--r-- | odb/relational/oracle/context.cxx | 795 | ||||
-rw-r--r-- | odb/relational/oracle/context.hxx | 188 | ||||
-rw-r--r-- | odb/relational/oracle/header.cxx | 230 | ||||
-rw-r--r-- | odb/relational/oracle/inline.cxx | 42 | ||||
-rw-r--r-- | odb/relational/oracle/model.cxx | 64 | ||||
-rw-r--r-- | odb/relational/oracle/schema.cxx | 696 | ||||
-rw-r--r-- | odb/relational/oracle/source.cxx | 646 |
9 files changed, 0 insertions, 3386 deletions
diff --git a/odb/relational/oracle/common.cxx b/odb/relational/oracle/common.cxx deleted file mode 100644 index 7caafc9..0000000 --- a/odb/relational/oracle/common.cxx +++ /dev/null @@ -1,522 +0,0 @@ -// file : odb/relational/oracle/common.cxx -// license : GNU GPL v3; see accompanying LICENSE file - -#include <cassert> - -#include <odb/relational/oracle/common.hxx> - -using namespace std; - -namespace relational -{ - namespace oracle - { - // - // 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) - { - // Numeric types. - // - case sql_type::NUMBER: - { - const sql_type& st (*mi.st); - - if (st.prec) - { - unsigned short r (st.prec_value); - - if (!st.scale) - { - if (r <= 10) - traverse_int32 (mi); - // Only OCI versions 11.2 and later support insertion and - // extraction into a 64 bit integer. - // - else if ( - (options.oracle_client_version () >= oracle_version (11, 2)) && - (r <= 19 || (r == 20 && unsigned_integer (mi.t)))) - traverse_int64 (mi); - else - traverse_big_int (mi); - } - else - { - // We can calculate the decimal exponent of the normalised - // floating point equivalent of the fixed point number using - // e = p - s, where p is the precision, s is the scale, and - // e the exponent. We can then use this to determine whether - // or not a value of Oracle SQL type NUMBER can be completely - // stored in the native floating point type. - // - - // The maximum decimal precision of a float is 7 significant - // digits. The minimum and maximum decimal exponents - // representable by a float are -37 and 38 respectively. - // - if (r <= 7) - { - int e = r - st.scale_value; - - if (e >= -37 && e <= 38) - traverse_float (mi); - else - traverse_double (mi); - } - - // The maximum decimal precision of a double is 15 significant - // digits. The minimum and maximum decimal exponent representable - // by a double exceeds that of the Oracle NUMBER type. - // - else if (r <= 15) - traverse_double (mi); - else - traverse_big_float (mi); - } - } - else - // If there is no precision, then this is a floating-point number. - // - traverse_double (mi); - - break; - } - case sql_type::FLOAT: - { - // We map FLOAT types based exclusively on their binary precision - // seeing that in 99% of cases it is the precision that is the - // limiting factor and not the exponent. - // - if (mi.st->prec_value <= 24) - traverse_float (mi); - else if (mi.st->prec_value <= 53) - traverse_double (mi); - else - traverse_big_float (mi); - - break; - } - case sql_type::BINARY_FLOAT: - { - traverse_float (mi); - break; - } - case sql_type::BINARY_DOUBLE: - { - traverse_double (mi); - break; - } - // Data-time types. - // - case sql_type::DATE: - { - traverse_date (mi); - break; - } - case sql_type::TIMESTAMP: - { - traverse_timestamp (mi); - break; - } - case sql_type::INTERVAL_YM: - { - traverse_interval_ym (mi); - break; - } - case sql_type::INTERVAL_DS: - { - traverse_interval_ds (mi); - break; - } - // String and binary types. - // - case sql_type::CHAR: - case sql_type::NCHAR: - case sql_type::VARCHAR2: - case sql_type::NVARCHAR2: - case sql_type::RAW: - { - traverse_string (mi); - break; - } - case sql_type::BLOB: - case sql_type::CLOB: - case sql_type::NCLOB: - { - traverse_lob (mi); - break; - } - case sql_type::invalid: - { - assert (false); - break; - } - } - } - - // - // member_image_type - // - - 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_oracle >::image_type"; - } - - void member_image_type:: - traverse_int32 (member_info& mi) - { - if (unsigned_integer (mi.t)) - type_ = "unsigned int"; - else - type_ = "int"; - } - - void member_image_type:: - traverse_int64 (member_info& mi) - { - if (unsigned_integer (mi.t)) - type_ = "unsigned long long"; - else - type_ = "long long"; - } - - void member_image_type:: - traverse_big_int (member_info&) - { - type_ = "char*"; - } - - void member_image_type:: - traverse_float (member_info&) - { - type_ = "float"; - } - - void member_image_type:: - traverse_double (member_info&) - { - type_ = "double"; - } - - void member_image_type:: - traverse_big_float (member_info&) - { - type_ = "char*"; - } - - void member_image_type:: - traverse_date (member_info&) - { - type_ = "char*"; - } - - void member_image_type:: - traverse_timestamp (member_info&) - { - type_ = "oracle::datetime"; - } - - void member_image_type:: - traverse_interval_ym (member_info&) - { - type_ = "oracle::interval_ym"; - } - - void member_image_type:: - traverse_interval_ds (member_info&) - { - type_ = "oracle::interval_ds"; - } - - void member_image_type:: - traverse_string (member_info&) - { - type_ = "char*"; - } - - void member_image_type:: - traverse_lob (member_info&) - { - type_ = "oracle::lob_callback"; - } - - entry<member_image_type> member_image_type_; - - // - // member_database_type - // - - namespace - { - const char* string_bin_database_id[] = - { - "id_string", // CHAR - "id_nstring", // NCHAR - "id_string", // VARCHAR2 - "id_nstring", // NVARCHAR2 - "id_raw" // RAW - }; - - const char* lob_database_id[] = - { - "id_blob", - "id_clob", - "id_nclob" - }; - } - - 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_int32 (member_info&) - { - type_id_ = "oracle::id_int32"; - } - - void member_database_type_id:: - traverse_int64 (member_info&) - { - type_id_ = "oracle::id_int64"; - } - - void member_database_type_id:: - traverse_big_int (member_info&) - { - type_id_ = "oracle::id_big_int"; - } - - void member_database_type_id:: - traverse_float (member_info&) - { - type_id_ = "oracle::id_float"; - } - - void member_database_type_id:: - traverse_double (member_info&) - { - type_id_ = "oracle::id_double"; - } - - void member_database_type_id:: - traverse_big_float (member_info&) - { - type_id_ = "oracle::id_big_float"; - } - - void member_database_type_id:: - traverse_date (member_info&) - { - type_id_ = "oracle::id_date"; - } - - void member_database_type_id:: - traverse_timestamp (member_info&) - { - type_id_ = "oracle::id_timestamp"; - } - - void member_database_type_id:: - traverse_interval_ym (member_info&) - { - type_id_ = "oracle::id_interval_ym"; - } - - void member_database_type_id:: - traverse_interval_ds (member_info&) - { - type_id_ = "oracle::id_interval_ds"; - } - - void member_database_type_id:: - traverse_string (member_info& mi) - { - type_id_ = string ("oracle::") + - string_bin_database_id[mi.st->type - sql_type::CHAR]; - } - - void member_database_type_id:: - traverse_lob (member_info& mi) - { - type_id_ = string ("oracle::") + - lob_database_id[mi.st->type - sql_type::BLOB]; - } - - entry<member_database_type_id> member_database_type_id_; - - // - // query_columns - // - - struct query_columns: relational::query_columns, context - { - query_columns (base const& x): base_impl (x) {} - - 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 = 0xFFF," << endl - << "short s = 0xFFF)" << 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::NUMBER: - { - if (st.prec) - { - os << ", " << st.prec_value; - - if (st.scale) - os << ", " << st.scale_value; - } - break; - } - case sql_type::FLOAT: - { - os << ", " << st.prec_value; - break; - } - case sql_type::TIMESTAMP: - { - os << ", " << st.prec_value; - break; - } - case sql_type::INTERVAL_YM: - { - os << ", " << st.prec_value; - break; - } - case sql_type::INTERVAL_DS: - { - // INTERVAL DAY TO SECOND has two precisions. - // - os << ", " << st.prec_value << ", " << st.scale_value; - break; - } - case sql_type::CHAR: - case sql_type::NCHAR: - case sql_type::VARCHAR2: - case sql_type::NVARCHAR2: - case sql_type::RAW: - { - // The same logic as in header.cxx. - // - size_t n (st.prec ? st.prec_value : 1); - - if (!st.byte_semantics) - n *= 4; - - if (st.type == sql_type::VARCHAR2 || - st.type == sql_type::NVARCHAR2) - n = n > 4000 ? 4000 : n; - else - n = n > 2000 ? 2000 : n; - - os << ", " << n; - break; - } - default: - { - break; - } - } - } - - virtual string - database_type_id (semantics::data_member& m) - { - return member_database_type_id_.database_type_id (m); - } - - private: - member_database_type_id member_database_type_id_; - }; - entry<query_columns> query_columns_; - } -} diff --git a/odb/relational/oracle/common.hxx b/odb/relational/oracle/common.hxx deleted file mode 100644 index 1958aab..0000000 --- a/odb/relational/oracle/common.hxx +++ /dev/null @@ -1,203 +0,0 @@ -// file : odb/relational/oracle/common.hxx -// license : GNU GPL v3; see accompanying LICENSE file - -#ifndef ODB_RELATIONAL_ORACLE_COMMON_HXX -#define ODB_RELATIONAL_ORACLE_COMMON_HXX - -#include <odb/relational/common.hxx> -#include <odb/relational/oracle/context.hxx> - -namespace relational -{ - namespace oracle - { - struct member_base: virtual relational::member_base_impl<sql_type>, context - { - member_base (base const& x): base (x), base_impl (x) {} - - // This c-tor is for the direct use inside the oracle 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_int32 (member_info&) - { - } - - virtual void - traverse_int64 (member_info&) - { - } - - virtual void - traverse_big_int (member_info&) - { - } - - virtual void - traverse_float (member_info&) - { - } - - virtual void - traverse_double (member_info&) - { - } - - virtual void - traverse_big_float (member_info&) - { - } - - virtual void - traverse_date (member_info&) - { - } - - virtual void - traverse_timestamp (member_info&) - { - } - - virtual void - traverse_interval_ym (member_info&) - { - } - - virtual void - traverse_interval_ds (member_info&) - { - } - - virtual void - traverse_string (member_info&) - { - } - - virtual void - traverse_lob (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_int32 (member_info&); - - virtual void - traverse_int64 (member_info&); - - virtual void - traverse_big_int (member_info&); - - virtual void - traverse_float (member_info&); - - virtual void - traverse_double (member_info&); - - virtual void - traverse_big_float (member_info&); - - virtual void - traverse_date (member_info&); - - virtual void - traverse_timestamp (member_info&); - - virtual void - traverse_interval_ym (member_info&); - - virtual void - traverse_interval_ds (member_info&); - - virtual void - traverse_string (member_info&); - - virtual void - traverse_lob (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_int32 (member_info&); - - virtual void - traverse_int64 (member_info&); - - virtual void - traverse_big_int (member_info&); - - virtual void - traverse_float (member_info&); - - virtual void - traverse_double (member_info&); - - virtual void - traverse_big_float (member_info&); - - virtual void - traverse_date (member_info&); - - virtual void - traverse_timestamp (member_info&); - - virtual void - traverse_interval_ym (member_info&); - - virtual void - traverse_interval_ds (member_info&); - - virtual void - traverse_string (member_info&); - - virtual void - traverse_lob (member_info&); - - private: - string type_id_; - }; - } -} -#endif // ODB_RELATIONAL_ORACLE_COMMON_HXX diff --git a/odb/relational/oracle/context.cxx b/odb/relational/oracle/context.cxx deleted file mode 100644 index 12ce0aa..0000000 --- a/odb/relational/oracle/context.cxx +++ /dev/null @@ -1,795 +0,0 @@ -// file : odb/relational/oracle/context.cxx -// license : GNU GPL v3; see accompanying LICENSE file - -#include <cassert> -#include <sstream> - -#include <odb/sql-token.hxx> -#include <odb/sql-lexer.hxx> - -#include <odb/relational/oracle/context.hxx> - -using namespace std; - -namespace relational -{ - namespace oracle - { - 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", "NUMBER(1)", 0, false}, - - {"char", "CHAR(1)", 0, false}, - {"signed char", "NUMBER(3)", 0, false}, - {"unsigned char", "NUMBER(3)", 0, false}, - - {"short int", "NUMBER(5)", 0, false}, - {"short unsigned int", "NUMBER(5)", 0, false}, - - {"int", "NUMBER(10)", 0, false}, - {"unsigned int", "NUMBER(10)", 0, false}, - - {"long int", "NUMBER(19)", 0, false}, - {"long unsigned int", "NUMBER(20)", 0, false}, - - {"long long int", "NUMBER(19)", 0, false}, - {"long long unsigned int", "NUMBER(20)", 0, false}, - - {"float", "BINARY_FLOAT", 0, false}, - {"double", "BINARY_DOUBLE", 0, false}, - - // Oracle treats empty VARCHAR2 (and NVARCHAR2) strings as NULL. - // - {"::std::string", "VARCHAR2(512)", 0, true}, - - {"::size_t", "NUMBER(20)", 0, false}, - {"::std::size_t", "NUMBER(20)", 0, false} - }; - } - - context* context::current_; - - context:: - ~context () - { - if (current_ == this) - current_ = 0; - } - - context:: - context (ostream& os, - semantics::unit& u, - options_type const& ops, - features_type& f, - sema_rel::model* m) - : root_context (os, u, ops, f, data_ptr (new (shared) data (os))), - base_context (static_cast<data*> (root_context::data_.get ()), m), - data_ (static_cast<data*> (base_context::data_)) - { - assert (current_ == 0); - current_ = this; - - generate_grow = false; - need_alias_as = false; - insert_send_auto_id = false; - delay_freeing_statement_result = false; - need_image_clone = true; - generate_bulk = true; - global_index = true; - global_fkey = true; - data_->bind_vector_ = "oracle::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; - - if (f) - f = false; - else - r += '.'; - - r += '"'; - r.append (*i, 0, 30); // Max identifier length is 30. - 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<array*> (&t)) - { - semantics::type& bt (a->base_type ()); - if (bt.is_a<semantics::fund_char> ()) - { - unsigned long long n (a->size ()); - - if (n == 0) - return r; - else if (n == 1) - r = "CHAR"; - else - { - r = "VARCHAR2"; - n--; - } - - // Oracle VARCHAR2 limit is 4000 bytes. Since there are no good - // alternatives (CLOB?), let the user specify the mapping. - // - if (n > 4000) - return ""; - - // Allow empty VARCHAR2 values. - // - if (null != 0 && r == "VARCHAR2") - *null = true; - - ostringstream ostr; - ostr << n; - r += '('; - r += ostr.str (); - r += ')'; - } - } - - return r; - } - - bool context:: - unsigned_integer (semantics::type& t) - { - semantics::type* wt (wrapper (t)); - const string& s ((wt == 0 ? t : utype (*wt)).name ()); - - return s == "bool" || - s == "unsigned char" || - s == "short unsigned int" || - s == "unsigned int" || - s == "long unsigned int" || - s == "long long unsigned int"; - } - - qname context:: - sequence_name (qname const& table) - { - string n; - - if (options.sequence_suffix ().count (db) != 0) - n = table.uname () + options.sequence_suffix ()[db]; - else - n = compose_name (table.uname (), "seq"); - - n = transform_name (n, sql_name_sequence); - - qname r (table.qualifier ()); - r.append (n); - return r; - } - - // - // SQL type parsing. - // - - sql_type const& context:: - parse_sql_type (string const& t, semantics::data_member& m, bool custom) - { - // If this proves to be too expensive, we can maintain a cache of - // parsed types across contexts. - // - data::sql_type_cache::iterator i (data_->sql_type_cache_.find (t)); - - if (i != data_->sql_type_cache_.end () - && (custom ? i->second.custom_cached : i->second.straight_cached)) - { - return (custom ? i->second.custom : i->second.straight); - } - else - { - try - { - sql_type st ( - parse_sql_type ( - t, - custom ? &unit.get<custom_db_types> ("custom-db-types") : 0)); - - if (custom) - return data_->sql_type_cache_[t].cache_custom (st); - else - return data_->sql_type_cache_[t].cache_straight (st); - } - catch (invalid_sql_type const& e) - { - cerr << m.file () << ":" << m.line () << ":" << m.column () - << ": error: " << e.message () << endl; - - throw operation_failed (); - } - } - } - - inline sql_type - error (bool fail, string const& m) - { - if (!fail) - return sql_type (); - else - throw context::invalid_sql_type (m); - } - - sql_type context:: - parse_sql_type (string sqlt, custom_db_types const* ct) - { - try - { - sql_type r; - - // First run the type through the custom mapping, if requested. - // - if (ct != 0) - { - for (custom_db_types::const_iterator i (ct->begin ()); - i != ct->end (); ++i) - { - custom_db_type const& t (*i); - - if (t.type.match (sqlt)) - { - r.to = t.type.replace (sqlt, t.to); - r.from = t.type.replace (sqlt, t.from); - sqlt = t.type.replace (sqlt, t.as); - break; - } - } - } - - sql_lexer l (sqlt); - - // While most type names use single identifier, there are - // a couple of exceptions to this rule: - // - // CHARACTER VARYING (VARCHAR2) - // CHAR VARYING (VARCHAR2) - // NATIONAL CHARACTER (NCHAR) - // NATIONAL CHAR (NCHAR) - // NCHAR VARYING (NVARCHAR2) - // NATIONAL CHARACTER VARYING (NVARCHAR2) - // NATIONAL CHAR VARYING (NVARCHAR2) - // NCHAR VARYING (NVARCHAR2) - // DOUBLE PRECISION (FLOAT(126)) - // INTERVAL YEAR TO MONTH - // INTERVAL DAY TO SECOND - // - enum state - { - parse_identifier, - parse_prec, - parse_done - }; - - state s (parse_identifier); - string prefix; - sql_token t (l.next ()); - - while (t.type () != sql_token::t_eos) - { - sql_token::token_type tt (t.type ()); - - switch (s) - { - case parse_identifier: - { - if (tt == sql_token::t_identifier) - { - string const& id (context::upcase (t.identifier ())); - - // - // Numeric types. - // - if ((id == "NUMBER") && prefix.empty ()) - { - // If NUMBER has no precision/scale, then it is a floating- - // point number. We indicate this by having no precision. - // - r.type = sql_type::NUMBER; - s = parse_prec; - } - else if ((id == "DEC" || id == "DECIMAL" || id == "NUMERIC") - && prefix.empty ()) - { - // DEC, DECIMAL, and NUMERIC are equivalent to NUMBER in - // all ways except that they may not represent a floating - // point number. The scale defaults to zero. - // - r.type = sql_type::NUMBER; - s = parse_prec; - } - else if ((id == "INT" || id == "INTEGER" || id == "SMALLINT") - && prefix.empty ()) - { - // INT, INTEGER, and SMALLINT map to NUMBER(38). They may not - // have precision or scale explicitly specified. - // - r.type = sql_type::NUMBER; - r.prec = true; - r.prec_value = 38; - - s = parse_done; - } - // - // Floating point types. - // - else if (id == "FLOAT" && prefix.empty ()) - { - r.type = sql_type::FLOAT; - r.prec = true; - r.prec_value = 126; - - s = parse_prec; - } - else if (id == "DOUBLE" && prefix.empty ()) - { - prefix = id; - } - else if (id == "PRECISION" && prefix == "DOUBLE") - { - r.type = sql_type::FLOAT; - r.prec = true; - r.prec_value = 126; - - s = parse_done; - } - else if (id == "REAL" && prefix.empty ()) - { - r.type = sql_type::FLOAT; - r.prec = true; - r.prec_value = 63; - - s = parse_done; - } - else if (id == "BINARY_FLOAT" && prefix.empty ()) - { - r.type = sql_type::BINARY_FLOAT; - s = parse_done; - } - else if (id == "BINARY_DOUBLE" && prefix.empty ()) - { - r.type = sql_type::BINARY_DOUBLE; - s = parse_done; - } - // - // Date-time types. - // - else if (id == "DATE" && prefix.empty ()) - { - r.type = sql_type::DATE; - s = parse_done; - } - else if (id == "TIMESTAMP" && prefix.empty ()) - { - prefix = id; - } - else if (id == "INTERVAL" && prefix.empty ()) - { - prefix = id; - } - else if (id == "YEAR" && prefix == "INTERVAL") - { - prefix += " "; - prefix += id; - - r.prec = true; - r.prec_value = 2; - s = parse_prec; - } - else if (id == "DAY" && prefix == "INTERVAL") - { - prefix += " "; - prefix += id; - - r.prec = true; - r.prec_value = 2; - s = parse_prec; - } - else if (id == "TO" && - (prefix == "INTERVAL YEAR" || - prefix == "INTERVAL DAY")) - { - prefix += " "; - prefix += id; - } - else if (id == "MONTH" && prefix == "INTERVAL YEAR TO") - { - r.type = sql_type::INTERVAL_YM; - s = parse_done; - } - else if (id == "SECOND" && prefix == "INTERVAL DAY TO") - { - r.type = sql_type::INTERVAL_DS; - - // Store seconds precision in scale since prec holds - // the days precision. - // - r.scale = true; - r.scale_value = 6; - s = parse_prec; - } - // - // Timestamp with time zone (not supported). - // - else if (id == "WITH" && prefix == "TIMESTAMP") - { - prefix += " "; - prefix += id; - } - else if (id == "TIME" && - (prefix == "TIMESTAMP WITH" || - prefix == "TIMESTAMP WITH LOCAL")) - { - prefix += " "; - prefix += id; - } - else if (id == "LOCAL" && prefix == "TIMESTAMP WITH") - { - prefix += " "; - prefix += id; - } - else if (id == "ZONE" && - (prefix == "TIMESTAMP WITH LOCAL TIME" || - prefix == "TIMESTAMP WITH TIME")) - { - return error (ct, "Oracle timestamps with time zones are " - "not currently supported"); - } - // - // String and binary types. - // - else if (id == "CHAR") - { - prefix += prefix.empty () ? "" : " "; - prefix += id; - } - else if (id == "CHARACTER") - { - prefix += prefix.empty () ? "" : " "; - prefix += id; - } - else if (id == "NCHAR") - { - prefix += prefix.empty () ? "" : " "; - prefix += id; - } - else if (id == "VARCHAR" || id == "VARCHAR2") - { - // VARCHAR is currently mapped to VARCHAR2 in Oracle server. - // However, this may change in future versions. - // - r.type = sql_type::VARCHAR2; - r.byte_semantics = true; - s = parse_prec; - } - else if (id == "NVARCHAR2") - { - r.type = sql_type::NVARCHAR2; - r.byte_semantics = false; - s = parse_prec; - } - else if (id == "VARYING") - { - // VARYING always appears at the end of an identifier. - // - if (prefix == "CHAR" || prefix == "CHARACTER") - { - r.type = sql_type::VARCHAR2; - r.byte_semantics = true; - } - else if (prefix == "NCHAR" || - prefix == "NATIONAL CHAR" || - prefix == "NATIONAL CHARACTER") - { - r.type = sql_type::NVARCHAR2; - r.byte_semantics = false; - } - - s = parse_prec; - } - else if (id == "NATIONAL" && prefix.empty ()) - { - prefix = id; - } - else if (id == "RAW" && prefix.empty ()) - { - r.type = sql_type::RAW; - s = parse_prec; - } - // - // LOB types. - // - else if (id == "BLOB" && prefix.empty ()) - { - r.type = sql_type::BLOB; - s = parse_done; - } - else if (id == "CLOB" && prefix.empty ()) - { - r.type = sql_type::CLOB; - s = parse_done; - } - else if (id == "NCLOB" && prefix.empty ()) - { - r.type = sql_type::NCLOB; - s = parse_done; - } - // - // LONG types. - // - else if (id == "LONG") - return error (ct, "Oracle LONG types are not supported"); - else - return error (ct, "unknown Oracle type '" + - t.identifier () + "'"); - - t = l.next (); - continue; - } - else if (!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; - r.byte_semantics = true; - r.prec = true; - r.prec_value = 1; - } - else if (prefix == "NCHAR" || - prefix == "NATIONAL CHAR" || - prefix == "NATIONAL CHARACTER") - { - r.type = sql_type::NCHAR; - r.byte_semantics = false; - r.prec = true; - r.prec_value = 1; - } - else if (prefix == "TIMESTAMP") - { - r.type = sql_type::TIMESTAMP; - r.prec = true; - r.prec_value = 6; - } - else - return error (ct, "incomplete Oracle type declaration: '" + - prefix + "'"); - - // All of the possible types handled in this block can take - // an optional precision specifier. Set the state and fall - // through to the parse_prec handler. - // - s = parse_prec; - } - else - { - assert (r.type == sql_type::invalid); - return error (ct, "unexepected '" + t.literal () + - "' in Oracle type declaration"); - } - } - // Fall through. - case parse_prec: - { - if (t.punctuation () == sql_token::p_lparen) - { - t = l.next (); - - if (t.type () != sql_token::t_int_lit) - { - return error (ct, "integer size/precision expected in " - "Oracle type declaration"); - } - - // Parse the precision. - // - { - unsigned short v; - istringstream is (t.literal ()); - - if (!(is >> v && is.eof ())) - { - return error (ct, "invalid prec value '" + t.literal () + - "' in Oracle type declaration"); - } - - // Store seconds precision in scale since prec holds - // the days precision for INTERVAL DAY TO SECOND. - // - if (r.type == sql_type::INTERVAL_DS) - { - r.scale = true; - r.scale_value = static_cast<short> (v); - } - else - { - r.prec = true; - r.prec_value = v; - } - - t = l.next (); - } - - // Parse the scale if present. - // - if (t.punctuation () == sql_token::p_comma) - { - // Scale can only be specified for NUMBER. - // - if (r.type != sql_type::NUMBER) - { - return error (ct, "invalid scale in Oracle type " - "declaration"); - } - - t = l.next (); - - if (t.type () != sql_token::t_int_lit) - { - return error (ct, "integer scale expected in Oracle type " - "declaration"); - } - - short v; - istringstream is (t.literal ()); - - if (!(is >> v && is.eof ())) - { - return error (ct, "invalid scale value '" + t.literal () + - "' in Oracle type declaration"); - } - - r.scale = true; - r.scale_value = v; - - t = l.next (); - } - else if (t.type () == sql_token::t_identifier) - { - const string& id (context::upcase (t.identifier ())); - - if (id == "CHAR") - r.byte_semantics = false; - else if (id != "BYTE") - { - return error (ct, "invalid keyword '" + t.literal () + - "' in Oracle type declaration"); - } - - t = l.next (); - } - - if (t.punctuation () != sql_token::p_rparen) - { - return error (ct, "expected ')' in Oracle type declaration"); - } - else - t = l.next (); - } - - s = r.type == sql_type::invalid ? parse_identifier : parse_done; - continue; - } - case parse_done: - { - return error (ct, "unexepected '" + t.literal () + "' in Oracle " - "type declaration"); - break; - } - } - } - - // Some prefixes can also be type names if not followed by the actual - // type name. - // - if (r.type == sql_type::invalid) - { - if (!prefix.empty ()) - { - if (prefix == "CHAR" || prefix == "CHARACTER") - { - r.type = sql_type::CHAR; - r.byte_semantics = true; - r.prec = true; - r.prec_value = 1; - } - else if (prefix == "NCHAR" || - prefix == "NATIONAL CHAR" || - prefix == "NATIONAL CHARACTER") - { - r.type = sql_type::NCHAR; - r.byte_semantics = false; - r.prec = true; - r.prec_value = 1; - } - else if (prefix == "TIMESTAMP") - { - r.type = sql_type::TIMESTAMP; - r.prec = true; - r.prec_value = 6; - } - else - return error (ct, "incomplete Oracle type declaration: '" + - prefix + "'"); - } - else - return error (ct, "invalid Oracle type declaration"); - } - - return r; - } - catch (sql_lexer::invalid_input const& e) - { - return error (ct, "invalid Oracle type declaration: " + e.message); - } - } - } -} diff --git a/odb/relational/oracle/context.hxx b/odb/relational/oracle/context.hxx deleted file mode 100644 index 6c55853..0000000 --- a/odb/relational/oracle/context.hxx +++ /dev/null @@ -1,188 +0,0 @@ -// file : odb/relational/oracle/context.hxx -// license : GNU GPL v3; see accompanying LICENSE file - -#ifndef ODB_RELATIONAL_ORACLE_CONTEXT_HXX -#define ODB_RELATIONAL_ORACLE_CONTEXT_HXX - -#include <map> - -#include <odb/relational/context.hxx> - -namespace relational -{ - namespace oracle - { - struct sql_type - { - // Keep the order in each block of types. - // - enum core_type - { - // Numeric types. - // - NUMBER, - FLOAT, - - // Floating point types. - // - BINARY_FLOAT, - BINARY_DOUBLE, - - // Date-time types. - // - DATE, - TIMESTAMP, - INTERVAL_YM, - INTERVAL_DS, - - // String and binary types. - // - CHAR, - NCHAR, - VARCHAR2, - NVARCHAR2, - RAW, - - // LOB types. - // - BLOB, - CLOB, - NCLOB, - - // Invalid type. - // - invalid - }; - - sql_type () : - type (invalid), prec (false), scale (false), byte_semantics (true) - { - } - - core_type type; - - bool prec; - unsigned short prec_value; // Oracle max value is 4000. - - bool scale; - short scale_value; // Oracle min value is -84. Max value is 127. - - bool byte_semantics; - - // 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); - - public: - // If necessary, unwraps. - // - static bool - unsigned_integer (semantics::type&); - - public: - // Construct sequence name from a given table name. - // - qname - sequence_name (qname const& table); - - 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<string, sql_type_cache_entry> sql_type_cache; - sql_type_cache sql_type_cache_; - }; - data* data_; - }; - } -} - -#endif // ODB_RELATIONAL_ORACLE_CONTEXT_HXX diff --git a/odb/relational/oracle/header.cxx b/odb/relational/oracle/header.cxx deleted file mode 100644 index bf50bb2..0000000 --- a/odb/relational/oracle/header.cxx +++ /dev/null @@ -1,230 +0,0 @@ -// file : odb/relational/oracle/header.cxx -// license : GNU GPL v3; see accompanying LICENSE file - -#include <odb/relational/header.hxx> - -#include <odb/relational/oracle/common.hxx> -#include <odb/relational/oracle/context.hxx> - -namespace relational -{ - namespace oracle - { - namespace header - { - namespace relational = relational::header; - - 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 << "oracle::change_callback change_callback_;" - << endl; - - os << "oracle::change_callback*" << endl - << "change_callback ()" - << "{"; - - if (gc) - os << "return &change_callback_;"; - else - os << "return 0;"; - - os << "}"; - } - } - } - }; - entry<image_type> image_type_; - - struct image_member: relational::image_member_impl<sql_type>, - member_base - { - image_member (base const& x) - : member_base::base (x), // virtual base - member_base::base_impl (x), // virtual base - base_impl (x), - member_base (x) {} - - virtual void - traverse_int32 (member_info& mi) - { - os << image_type << " " << mi.var << "value;" - << "sb2 " << mi.var << "indicator;" - << endl; - } - - virtual void - traverse_int64 (member_info& mi) - { - os << image_type << " " << mi.var << "value;" - << "sb2 " << mi.var << "indicator;" - << endl; - } - - virtual void - traverse_big_int (member_info& mi) - { - // Each significant base-100 digit requires a byte of storage - // in the manitissa. The default precision is 38 decimal digits, - // which is equivalent to 19 base-100 digits. - // - size_t n (19); - - if (mi.st->prec) - n = mi.st->prec_value / 2 + mi.st->prec_value % 2; - - // We require an additional byte for each of the exponent and - // negative value terminator values. - // - n += 2; - - os << "char " << mi.var << "value[" << n << "];" - << "ub2 " << mi.var << "size;" - << "sb2 " << mi.var << "indicator;" - << endl; - } - - virtual void - traverse_float (member_info& mi) - { - os << image_type << " " << mi.var << "value;" - << "sb2 " << mi.var << "indicator;" - << endl; - } - - virtual void - traverse_double (member_info& mi) - { - os << image_type << " " << mi.var << "value;" - << "sb2 " << mi.var << "indicator;" - << endl; - } - - virtual void - traverse_big_float (member_info& mi) - { - // big_float is mapped to the OCI type SQLT_NUM, which requires 21 - // bytes of storage. - // - os << "char " << mi.var << "value[21];" - << "ub2 " << mi.var << "size;" - << "sb2 " << mi.var << "indicator;" - << endl; - } - - virtual void - traverse_date (member_info& mi) - { - os << "char " << mi.var << "value[7];" - << "sb2 " << mi.var << "indicator;" - << endl; - } - - virtual void - traverse_timestamp (member_info& mi) - { - os << image_type << " " << mi.var << "value;" - << "sb2 " << mi.var << "indicator;" - << endl; - } - - virtual void - traverse_interval_ym (member_info& mi) - { - os << image_type << " " << mi.var << "value;" - << "sb2 " << mi.var << "indicator;" - << endl; - } - - virtual void - traverse_interval_ds (member_info& mi) - { - os << image_type << " " << mi.var << "value;" - << "sb2 " << mi.var << "indicator;" - << endl; - } - - virtual void - traverse_string (member_info& mi) - { - size_t n (mi.st->prec ? mi.st->prec_value : 1); - - // National characters can be either UTF-8 or UTF-16 encoded, - // both of which have a maximum character encoding size of 4 - // bytes. Database character set can also be UTF-8 so if the - // size is specified in characters, then conservatively assume - // each character can take up to 4 bytes. - // - if (!mi.st->byte_semantics) // N*CHAR always has CHAR semantics. - n *= 4; - - if (mi.st->type == sql_type::VARCHAR2 || - mi.st->type == sql_type::NVARCHAR2) - n = n > 4000 ? 4000 : n; - else - n = n > 2000 ? 2000 : n; - - os << "char " << mi.var << "value[" << n << "];" - << "ub2 " << mi.var << "size;" - << "sb2 " << mi.var << "indicator;" - << endl; - } - - virtual void - traverse_lob (member_info& mi) - { - os << "mutable " << image_type << " " << mi.var << "callback;" - << "sb2 " << mi.var << "indicator;" - << "oracle::lob " << mi.var << "lob;" - << endl; - } - }; - entry<image_member> image_member_; - - struct class1: relational::class1 - { - 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<unsigned long long> ("bulk") - : 1); - - os << "static const std::size_t batch = " << b << "UL;" - << endl; - } - } - }; - entry<class1> class1_entry_; - } - } -} diff --git a/odb/relational/oracle/inline.cxx b/odb/relational/oracle/inline.cxx deleted file mode 100644 index 1b6d606..0000000 --- a/odb/relational/oracle/inline.cxx +++ /dev/null @@ -1,42 +0,0 @@ -// file : odb/relational/oracle/inline.cxx -// license : GNU GPL v3; see accompanying LICENSE file - -#include <odb/relational/inline.hxx> - -#include <odb/relational/oracle/common.hxx> -#include <odb/relational/oracle/context.hxx> - -using namespace std; - -namespace relational -{ - namespace oracle - { - namespace inline_ - { - namespace relational = relational::inline_; - - struct null_member: relational::null_member_impl<sql_type>, - member_base - { - null_member (base const& x) - : member_base::base (x), // virtual base - member_base::base_impl (x), // virtual base - base_impl (x), - member_base (x) - { - } - - virtual void - traverse_simple (member_info& mi) - { - if (get_) - os << "r = r && i." << mi.var << "indicator == -1;"; - else - os << "i." << mi.var << "indicator = -1;"; - } - }; - entry<null_member> null_member_; - } - } -} diff --git a/odb/relational/oracle/model.cxx b/odb/relational/oracle/model.cxx deleted file mode 100644 index b65e201..0000000 --- a/odb/relational/oracle/model.cxx +++ /dev/null @@ -1,64 +0,0 @@ -// file : odb/relational/oracle/model.cxx -// license : GNU GPL v3; see accompanying LICENSE file - -#include <sstream> - -#include <odb/relational/model.hxx> - -#include <odb/relational/oracle/common.hxx> -#include <odb/relational/oracle/context.hxx> - -using namespace std; - -namespace relational -{ - namespace oracle - { - 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 Oracle NUMBER. - // - sql_type const& t (parse_sql_type (column_type (), m, false)); - if (t.type != sql_type::NUMBER) - { - cerr << m.file () << ":" << m.line () << ":" << m.column () - << ": error: column with default value specified as C++ " - << "enumerator must map to Oracle NUMBER" << endl; - - throw operation_failed (); - } - - using semantics::enumerator; - - enumerator& e (dynamic_cast<enumerator&> (*unit.find (en))); - - ostringstream ostr; - - if (e.enum_ ().unsigned_ ()) - ostr << e.value (); - else - ostr << static_cast<long long> (e.value ()); - - return ostr.str (); - } - - virtual void - primary_key (sema_rel::primary_key& pk) - { - if (pk.auto_ ()) - pk.extra ()["sequence"] = sequence_name (table_.name ()).string (); - } - }; - entry<object_columns> object_columns_; - } - } -} diff --git a/odb/relational/oracle/schema.cxx b/odb/relational/oracle/schema.cxx deleted file mode 100644 index 75100b1..0000000 --- a/odb/relational/oracle/schema.cxx +++ /dev/null @@ -1,696 +0,0 @@ -// file : odb/relational/oracle/schema.cxx -// license : GNU GPL v3; see accompanying LICENSE file - -#include <map> -#include <utility> // pair - -#include <odb/diagnostics.hxx> - -#include <odb/relational/schema.hxx> - -#include <odb/relational/oracle/common.hxx> -#include <odb/relational/oracle/context.hxx> - -using namespace std; - -namespace relational -{ - namespace oracle - { - 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 - line (const std::string& l) - { - // SQLPlus doesn't like empty line in the middle of a statement. - // - if (!l.empty ()) - { - base::line (l); - last_ = l; - } - } - - virtual void - post () - { - if (!first_) // Ignore empty statements. - { - if (last_ == "END;") - os << endl - << '/' << endl - << endl; - - else - os << ';' << endl - << endl; - } - } - - private: - string last_; - }; - entry<sql_emitter> sql_emitter_; - - // - // File. - // - - struct sql_file: relational::sql_file, context - { - sql_file (const base& x): base (x) {} - - virtual void - prologue () - { - // Quiet down SQLPlus and make sure it exits with an error - // code if there is an error. - // - os << "SET FEEDBACK OFF;" << endl - << "WHENEVER SQLERROR EXIT FAILURE;" << endl - << "WHENEVER OSERROR EXIT FAILURE;" << endl - << endl; - } - - virtual void - epilogue () - { - os << "EXIT;" << endl; - } - }; - entry<sql_file> 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> drop_column_; - - struct drop_foreign_key: relational::drop_foreign_key, context - { - drop_foreign_key (base const& x): base (x) {} - - virtual void - traverse (sema_rel::drop_foreign_key& dfk) - { - os << endl; - drop (dfk); - } - }; - entry<drop_foreign_key> drop_foreign_key_; - - struct drop_index: relational::drop_index, context - { - drop_index (base const& x): base (x) {} - - virtual string - name (sema_rel::index& in) - { - // In Oracle, index names can be qualified with the schema. - // - sema_rel::table& t (static_cast<sema_rel::table&> (in.scope ())); - sema_rel::qname n (t.name ().qualifier ()); - n.append (in.name ()); - return quote_id (n); - } - }; - entry<drop_index> 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) - { - using sema_rel::primary_key; - - sema_rel::table::names_iterator i (t.find ("")); // Special name. - primary_key* pk (i != t.names_end () - ? &dynamic_cast<primary_key&> (i->nameable ()) - : 0); - - string qt (quote_id (t.name ())); - string qs (pk != 0 && pk->auto_ () - ? quote_id (qname::from_string (pk->extra ()["sequence"])) - : ""); - - if (migration) - { - pre_statement (); - os << "DROP TABLE " << qt << endl; - post_statement (); - - // Drop the sequence if we have auto primary key. - // - if (!qs.empty ()) - { - pre_statement (); - os << "DROP SEQUENCE " << qs << endl; - post_statement (); - } - } - else - { - // Oracle has no IF EXISTS conditional for dropping objects. The - // PL/SQL approach below seems to be the least error-prone and the - // most widely used of the alternatives. - // - pre_statement (); - os << "BEGIN" << endl - << " BEGIN" << endl - << " EXECUTE IMMEDIATE 'DROP TABLE " << qt << " CASCADE " << - "CONSTRAINTS';" << endl - << " EXCEPTION" << endl - << " WHEN OTHERS THEN" << endl - << " IF SQLCODE != -942 THEN RAISE; END IF;" << endl - << " END;" << endl; - - // Drop the sequence if we have auto primary key. - // - if (!qs.empty ()) - { - os << " BEGIN" << endl - << " EXECUTE IMMEDIATE 'DROP SEQUENCE " << qs << - "';" << endl - << " EXCEPTION" << endl - << " WHEN OTHERS THEN" << endl - << " IF SQLCODE != -2289 THEN RAISE; END IF;" << endl - << " END;" << endl; - } - - os << "END;" << endl; - post_statement (); - } - } - - virtual void - traverse (sema_rel::table& t, bool migration) - { - // For migration drop foreign keys explicitly in pre-migration. - // - if (migration) - { - base::traverse (t, migration); - return; - } - - // For schema creation we use the CASCADE clause to drop foreign - // keys. - // - if (pass_ != 2) - return; - - drop (t, migration); - } - }; - entry<drop_table> drop_table_; - - // - // Create. - // - static sema_rel::uname - truncate (location const& l, const char* kind, sema_rel::uname n, bool w) - { - if (n.size () > 30) - { - if (w) - warn (l) << kind << " name '" << n << "' is longer than 30 " - << "characters and will be truncated" << endl; - - n.resize (30); - } - - return n; - } - - static sema_rel::qname - truncate (location const& l, - const char* kind, - sema_rel::qname const& n, - bool w) - { - // Don't bother verifying the schema name since that is - // specified explicitly and in a single place. - // - qname r (n.qualifier ()); - r.append (truncate (l, kind, n.uname (), w)); - return r; - } - - template <typename N> - struct scope - { - typedef std::map<N, pair<N, location> > map; - - scope (const char* k, const char* p, bool w) - : kind_ (k), prag_ (p), warn_ (w) {} - - void - check (location const& l, N const& n) - { - N tn (truncate (l, kind_, n, warn_)); - - pair<typename map::iterator, bool> r ( - map_.insert (make_pair (tn, make_pair (n, l)))); - - if (r.second) - return; - - error (l) << kind_ << " name '" << tn << "' conflicts with an " - << "already defined " << kind_ << " name" << endl; - - if (tn != n) - info (l) << kind_ << " name '" << tn << "' is truncated '" - << n << "'" << endl; - - N const& n1 (r.first->second.first); - location const& l1 (r.first->second.second); - - info (l1) << "conflicting " << kind_ << " is defined here" << endl; - - if (tn != n) - info (l1) << "conflicting " << kind_ << " name '" << tn - << "' is truncated '" << n1 << "'" << endl; - - info (l) << "use #pragma db " << prag_ << " to change one of " - << "the names" << endl; - - throw operation_failed (); - } - - void - clear () {map_.clear ();} - - const char* kind_; - const char* prag_; - bool warn_; - map map_; - }; - - struct scopes - { - scopes (bool warn) - : tables ("table", "table", warn), - fkeys ("foreign key", "column", warn), // Change column name. - indexes ("index", "index", warn), - sequences ("sequence", "table", warn), // Change table name. - columns ("column", "column", warn) {} - - // In Oracle, all these entities are in their own name spaces, - // as in an index and a foreign key with the same name do not - // conflict. - // - scope<sema_rel::qname> tables; - scope<sema_rel::uname> fkeys; // Global but can't have schema. - scope<sema_rel::qname> indexes; - scope<sema_rel::qname> sequences; - scope<sema_rel::uname> columns; - }; - - struct create_column: relational::create_column, context - { - create_column (base const& x): base (x) {} - - virtual void - traverse (sema_rel::column& c) - { - // Check name trunction and conflicts. - // - if (scopes* s = static_cast<scopes*> (context::extra)) - s->columns.check (c.get<location> ("cxx-location"), c.name ()); - - base::traverse (c); - } - - virtual void - traverse (sema_rel::add_column& ac) - { - if (first_) - first_ = false; - else - os << "," << endl - << " "; - - create (ac); - } - - virtual void - constraints (sema_rel::column& c, sema_rel::primary_key* pk) - { - // Oracle wants DEFAULT before NULL even though we can end - // up with mouthfulls like DEFAULT NULL NULL. - // - if (!c.default_ ().empty ()) - os << " DEFAULT " << c.default_ (); - - null (c); - - // If this is a single-column primary key, generate it inline. - // - if (pk != 0 && pk->contains_size () == 1) - primary_key (); - - if (pk != 0 && pk->auto_ ()) - auto_ (*pk); - } - }; - entry<create_column> create_column_; - - struct create_foreign_key: relational::create_foreign_key, context - { - create_foreign_key (base const& x): base (x) {} - - virtual void - traverse_create (sema_rel::foreign_key& fk) - { - // Check name trunction and conflicts. - // - if (scopes* s = static_cast<scopes*> (context::extra)) - s->fkeys.check (fk.get<location> ("cxx-location"), fk.name ()); - - base::traverse_create (fk); - } - - virtual void - traverse_add (sema_rel::foreign_key& fk) - { - // Check name trunction and conflicts. - // - if (scopes* s = static_cast<scopes*> (context::extra)) - s->fkeys.check (fk.get<location> ("cxx-location"), fk.name ()); - - os << endl - << " ADD CONSTRAINT "; - create (fk); - } - }; - entry<create_foreign_key> create_foreign_key_; - - struct create_index: relational::create_index, context - { - create_index (base const& x): base (x) {} - - virtual string - name (sema_rel::index& in) - { - // In Oracle, index names can be qualified with the schema. - // - sema_rel::table& t (static_cast<sema_rel::table&> (in.scope ())); - sema_rel::qname n (t.name ().qualifier ()); - n.append (in.name ()); - - // Check name trunction and conflicts. - // - if (scopes* s = static_cast<scopes*> (context::extra)) - s->indexes.check (in.get<location> ("cxx-location"), n); - - return quote_id (n); - } - }; - entry<create_index> create_index_; - - struct create_table: relational::create_table, context - { - create_table (base const& x): base (x) {} - - void - traverse (sema_rel::table& t) - { - // Check name trunction and conflicts. - // - if (scopes* s = static_cast<scopes*> (context::extra)) - { - if (pass_ == 1) - { - s->tables.check (t.get<location> ("cxx-location"), t.name ()); - s->columns.clear (); - } - } - - base::traverse (t); - - if (pass_ == 1) - { - // Create the sequence if we have auto primary key. - // - using sema_rel::primary_key; - - sema_rel::table::names_iterator i (t.find ("")); // Special name. - primary_key* pk (i != t.names_end () - ? &dynamic_cast<primary_key&> (i->nameable ()) - : 0); - - if (pk != 0 && pk->auto_ ()) - { - // Already qualified with the table's schema, if any. - // - sema_rel::qname n ( - qname::from_string (pk->extra ()["sequence"])); - - if (scopes* s = static_cast<scopes*> (context::extra)) - s->sequences.check (pk->get<location> ("cxx-location"), n); - - pre_statement (); - os_ << "CREATE SEQUENCE " << quote_id (n) << endl - << " START WITH 1 INCREMENT BY 1" << endl; - post_statement (); - } - } - } - }; - entry<create_table> create_table_; - - struct create_model: relational::create_model, context - { - create_model (base const& x): base (x) {} - - void - traverse (sema_rel::model& m) - { - scopes s (options.oracle_warn_truncation ()); - context::extra = &s; - base::traverse (m); - context::extra = 0; - } - }; - entry<create_model> create_model_; - - // - // 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; - - if (first_) - first_ = false; - else - os << "," << endl - << " "; - - os << quote_id (c.name ()) << (c.null () ? " NULL" : " NOT NULL"); - } - }; - entry<alter_column> alter_column_; - - struct alter_table_pre: relational::alter_table_pre, context - { - alter_table_pre (base const& x): base (x) {} - - virtual void - alter (sema_rel::alter_table& at) - { - // Oracle can only alter certain kinds of things together but - // grouped one at a time. - // - if (check<sema_rel::drop_foreign_key> (at)) - { - pre_statement (); - - os << "ALTER TABLE " << quote_id (at.name ()); - - instance<drop_foreign_key> dfc (*this); - trav_rel::unames n (*dfc); - names (at, n); - os << endl; - - post_statement (); - } - - if (check<sema_rel::add_column> (at)) - { - pre_statement (); - - os << "ALTER TABLE " << quote_id (at.name ()) << endl - << " ADD ("; - - instance<create_column> cc (*this); - trav_rel::unames n (*cc); - names (at, n); - os << ")" << endl; - - post_statement (); - } - - if (check_alter_column_null (at, true)) - { - pre_statement (); - - os << "ALTER TABLE " << quote_id (at.name ()) << endl - << " MODIFY ("; - - bool tl (true); // (Im)perfect forwarding. - instance<alter_column> ac (*this, tl); - trav_rel::unames n (*ac); - names (at, n); - os << ")" << endl; - - post_statement (); - } - } - }; - entry<alter_table_pre> alter_table_pre_; - - struct alter_table_post: relational::alter_table_post, context - { - alter_table_post (base const& x): base (x) {} - - virtual void - alter (sema_rel::alter_table& at) - { - // Oracle can only alter certain kinds of things together but - // grouped one at a time. - // - if (check<sema_rel::drop_column> (at)) - { - pre_statement (); - - os << "ALTER TABLE " << quote_id (at.name ()) << endl - << " DROP ("; - - instance<drop_column> dc (*this); - trav_rel::unames n (*dc); - names (at, n); - os << ")" << endl; - - post_statement (); - } - - if (check_alter_column_null (at, false)) - { - pre_statement (); - - os << "ALTER TABLE " << quote_id (at.name ()) << endl - << " MODIFY ("; - - bool fl (false); // (Im)perfect forwarding. - instance<alter_column> ac (*this, fl); - trav_rel::unames n (*ac); - names (at, n); - os << ")" << endl; - - post_statement (); - } - - if (check<sema_rel::add_foreign_key> (at)) - { - pre_statement (); - - os << "ALTER TABLE " << quote_id (at.name ()); - - instance<create_foreign_key> cfc (*this); - trav_rel::unames n (*cfc); - names (at, n); - os << endl; - - post_statement (); - } - } - }; - entry<alter_table_post> alter_table_post_; - - // - // Schema version table. - // - - struct version_table: relational::version_table, context - { - version_table (base const& x) - : base (x) - { - // If the schema name is empty, replace it with a single space - // to workaround the VARCHAR2 empty/NULL issue. - // - if (qs_ == "''") - qs_ = "' '"; - } - - virtual void - create_table () - { - pre_statement (); - - os << "BEGIN" << endl - << " EXECUTE IMMEDIATE 'CREATE TABLE " << qt_ << " (" << endl - << " " << qn_ << " VARCHAR2(512) NOT NULL PRIMARY KEY," << endl - << " " << qv_ << " NUMBER(20) NOT NULL," << endl - << " " << qm_ << " NUMBER(1) NOT NULL)';" << endl - << "EXCEPTION" << endl - << " WHEN OTHERS THEN" << endl - << " IF SQLCODE != -955 THEN RAISE; END IF;" << endl - << "END;" << endl; - - post_statement (); - } - - virtual void - create (sema_rel::version v) - { - pre_statement (); - - os << "MERGE INTO " << qt_ << " USING DUAL ON (" << qn_ << " = " << - qs_ << ")" << endl - << " WHEN NOT MATCHED THEN INSERT (" << endl - << " " << qn_ << ", " << qv_ << ", " << qm_ << ")" << endl - << " VALUES (" << qs_ << ", " << v << ", 0)" << endl; - - post_statement (); - } - }; - entry<version_table> version_table_; - } - } -} diff --git a/odb/relational/oracle/source.cxx b/odb/relational/oracle/source.cxx deleted file mode 100644 index adf9864..0000000 --- a/odb/relational/oracle/source.cxx +++ /dev/null @@ -1,646 +0,0 @@ -// file : odb/relational/oracle/source.cxx -// license : GNU GPL v3; see accompanying LICENSE file - -#include <odb/relational/source.hxx> - -#include <odb/relational/oracle/common.hxx> -#include <odb/relational/oracle/context.hxx> - -using namespace std; - -namespace relational -{ - namespace oracle - { - namespace source - { - namespace relational = relational::source; - - struct query_parameters: relational::query_parameters, context - { - query_parameters (base const& x): base (x), i_ (0) {} - - virtual string - next (semantics::data_member&, const string&, const string&) - { - ostringstream ss; - ss << ":" << ++i_; - - return ss.str (); - } - - virtual string - auto_id (semantics::data_member&, const string&, const string&) - { - return quote_id (sequence_name (table_)) + ".nextval"; - } - - private: - size_t i_; - }; - entry<query_parameters> query_parameters_; - - namespace - { - const char* string_buffer_types[] = - { - "oracle::bind::string", // CHAR - "oracle::bind::nstring", // NCHAR - "oracle::bind::string", // VARCHAR2 - "oracle::bind::nstring", // NVARCHAR2 - "oracle::bind::raw" // RAW - }; - - const char* lob_buffer_types[] = - { - "oracle::bind::blob", - "oracle::bind::clob", - "oracle::bind::nclob" - }; - } - - // - // bind - // - - struct bind_member: relational::bind_member_impl<sql_type>, - member_base - { - bind_member (base const& x) - : member_base::base (x), // virtual base - member_base::base_impl (x), // virtual base - base_impl (x), - member_base (x) - { - } - - virtual void - traverse_int32 (member_info& mi) - { - os << b << ".type = oracle::bind::" << - (unsigned_integer (mi.t) ? "uinteger" : "integer") << ";" - << b << ".buffer = &" << arg << "." << mi.var << "value;" - << b << ".capacity = 4;" - << b << ".size = 0;" - << b << ".indicator = &" << arg << "." << mi.var << "indicator;"; - } - - virtual void - traverse_int64 (member_info& mi) - { - os << b << ".type = oracle::bind::" << - (unsigned_integer (mi.t) ? "uinteger" : "integer") << ";" - << b << ".buffer= &" << arg << "." << mi.var << "value;" - << b << ".capacity = 8;" - << b << ".size = 0;" - << b << ".indicator = &" << arg << "." << mi.var << "indicator;"; - } - - virtual void - traverse_big_int (member_info& mi) - { - os << b << ".type = oracle::bind::number;" - << b << ".buffer = " << arg << "." << mi.var << "value;" - << b << ".capacity = static_cast<ub4> (sizeof (" << arg << - "." << mi.var << "value));" - << b << ".size = &" << arg << "." << mi.var << "size;" - << b << ".indicator = &" << arg << "." << mi.var << "indicator;"; - } - - virtual void - traverse_float (member_info& mi) - { - os << b << ".type = oracle::bind::binary_float;" - << b << ".buffer= &" << arg << "." << mi.var << "value;" - << b << ".capacity = 4;" - << b << ".size = 0;" - << b << ".indicator = &" << arg << "." << mi.var << "indicator;"; - } - - virtual void - traverse_double (member_info& mi) - { - os << b << ".type = oracle::bind::binary_double;" - << b << ".buffer= &" << arg << "." << mi.var << "value;" - << b << ".capacity = 8;" - << b << ".size = 0;" - << b << ".indicator = &" << arg << "." << mi.var << "indicator;"; - } - - virtual void - traverse_big_float (member_info& mi) - { - os << b << ".type = oracle::bind::number;" - << b << ".buffer = " << arg << "." << mi.var << "value;" - << b << ".capacity = static_cast<ub4> (sizeof (" << arg << "." << - mi.var << "value));" - << b << ".size = &" << arg << "." << mi.var << "size;" - << b << ".indicator = &" << arg << "." << mi.var << "indicator;"; - } - - virtual void - traverse_date (member_info& mi) - { - os << b << ".type = oracle::bind::date;" - << b << ".buffer = " << arg << "." << mi.var << "value;" - << b << ".capacity = static_cast<ub4> (sizeof (" << arg << "." << - mi.var << "value));" - << b << ".size = 0;" - << b << ".indicator = &" << arg << "." << mi.var << "indicator;"; - } - - virtual void - traverse_timestamp (member_info& mi) - { - os << b << ".type = oracle::bind::timestamp;" - << b << ".buffer = &" << arg << "." << mi.var << "value;" - << b << ".indicator = &" << arg << "." << mi.var << "indicator;"; - } - - virtual void - traverse_interval_ym (member_info& mi) - { - os << b << ".type = oracle::bind::interval_ym;" - << b << ".buffer = &" << arg << "." << mi.var << "value;" - << b << ".indicator = &" << arg << "." << mi.var << "indicator;"; - } - - virtual void - traverse_interval_ds (member_info& mi) - { - os << b << ".type = oracle::bind::interval_ds;" - << b << ".buffer = &" << arg << "." << mi.var << "value;" - << b << ".indicator = &" << arg << "." << mi.var << "indicator;"; - } - - virtual void - traverse_string (member_info& mi) - { - os << b << ".type = " << - string_buffer_types[mi.st->type - sql_type::CHAR] << ";" - << b << ".buffer = " << arg << "." << mi.var << "value;" - << b << ".capacity = static_cast<ub4> (sizeof (" << arg << - "." << mi.var << "value));" - << b << ".size = &" << arg << "." << mi.var << "size;" - << b << ".indicator = &" << arg << "." << mi.var << "indicator;"; - } - - virtual void - traverse_lob (member_info& mi) - { - os << b << ".type = " << - lob_buffer_types[mi.st->type - sql_type::BLOB] << ";" - << b << ".buffer = &" << arg << "." << mi.var << "lob;" - << b << ".indicator = &" << arg << "." << mi.var << "indicator;" - << b << ".callback = &" << arg << "." << mi.var << "callback;" - << endl; - } - }; - entry<bind_member> bind_member_; - - // - // init image - // - - struct init_image_member: relational::init_image_member_impl<sql_type>, - member_base - { - init_image_member (base const& x) - : member_base::base (x), // virtual base - member_base::base_impl (x), // virtual base - base_impl (x), - member_base (x) - { - } - - virtual void - check_accessor (member_info& mi, member_access& ma) - { - // We cannot use accessors that return by-value for LOB - // members. - // - if ((mi.st->type == sql_type::BLOB || - mi.st->type == sql_type::CLOB || - mi.st->type == sql_type::NCLOB) && - ma.by_value) - { - error (ma.loc) << "accessor returning a value cannot be used " - << "for a data member of Oracle LOB 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 - set_null (member_info& mi) - { - os << "i." << mi.var << "indicator = -1;"; - } - - virtual void - traverse_int32 (member_info& mi) - { - os << traits << "::set_image (" << endl - << "i." << mi.var << "value, is_null, " << member << ");" - << "i." << mi.var << "indicator = is_null ? -1 : 0;"; - } - - virtual void - traverse_int64 (member_info& mi) - { - os << traits << "::set_image (" << endl - << "i." << mi.var << "value, is_null, " << member << ");" - << "i." << mi.var << "indicator = is_null ? -1 : 0;"; - } - - virtual void - traverse_big_int (member_info& mi) - { - os << "std::size_t size (0);" - << traits << "::set_image (" << endl - << "i." << mi.var << "value," << endl - << "size," << endl - << "is_null," << endl - << member << ");" - << "i." << mi.var << "indicator = is_null ? -1 : 0;" - << "i." << mi.var << "size = static_cast<ub2> (size);"; - } - - virtual void - traverse_float (member_info& mi) - { - os << traits << "::set_image (" << endl - << "i." << mi.var << "value, is_null, " << member << ");" - << "i." << mi.var << "indicator = is_null ? -1 : 0;"; - } - - virtual void - traverse_double (member_info& mi) - { - os << traits << "::set_image (" << endl - << "i." << mi.var << "value, is_null, " << member << ");" - << "i." << mi.var << "indicator = is_null ? -1 : 0;"; - } - - virtual void - traverse_big_float (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 << "indicator = is_null ? -1 : 0;" - << "i." << mi.var << "size = static_cast<ub2> (size);"; - } - - virtual void - traverse_date (member_info& mi) - { - os << traits << "::set_image (" << endl - << "i." << mi.var << "value, is_null, " << member << ");" - << "i." << mi.var << "indicator = is_null ? -1 : 0;"; - } - - virtual void - traverse_timestamp (member_info& mi) - { - os << traits << "::set_image (" << endl - << "i." << mi.var << "value, is_null, " << member << ");" - << "i." << mi.var << "indicator = is_null ? -1 : 0;"; - } - - virtual void - traverse_interval_ym (member_info& mi) - { - os << traits << "::set_image (" << endl - << "i." << mi.var << "value, is_null, " << member << ");" - << "i." << mi.var << "indicator = is_null ? -1 : 0;"; - } - - virtual void - traverse_interval_ds (member_info& mi) - { - os << traits << "::set_image (" << endl - << "i." << mi.var << "value, is_null, " << member << ");" - << "i." << mi.var << "indicator = is_null ? -1 : 0;"; - } - - virtual void - traverse_string (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 << "indicator = is_null ? -1 : 0;" - << "i." << mi.var << "size = static_cast<ub2> (size);"; - } - - virtual void - traverse_lob (member_info& mi) - { - os << "i." << mi.var << "lob.position = 0;" - << 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 << "indicator = is_null ? -1 : 0;"; - } - }; - entry<init_image_member> init_image_member_; - - // - // init value - // - - struct init_value_member: relational::init_value_member_impl<sql_type>, - member_base - { - init_value_member (base const& x) - : member_base::base (x), // virtual base - member_base::base_impl (x), // virtual base - base_impl (x), - member_base (x) - { - } - - virtual void - get_null (string const& var) const - { - os << "i." << var << "indicator == -1"; - } - - virtual void - check_modifier (member_info& mi, member_access& ma) - { - // We cannot use by-value modifier for LOB members. - // - if ((mi.st->type == sql_type::BLOB || - mi.st->type == sql_type::CLOB || - mi.st->type == sql_type::NCLOB) && - ma.placeholder ()) - { - error (ma.loc) << "modifier accepting a value cannot be used " - << "for a data member of Oracle LOB 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_int32 (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "i." << mi.var << "indicator == -1);" - << endl; - } - - virtual void - traverse_int64 (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "i." << mi.var << "indicator == -1);" - << endl; - } - - virtual void - traverse_big_int (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "i." << mi.var << "size," << endl - << "i." << mi.var << "indicator == -1);" - << endl; - } - - virtual void - traverse_float (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "i." << mi.var << "indicator == -1);" - << endl; - } - - virtual void - traverse_double (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "i." << mi.var << "indicator == -1);" - << endl; - } - - virtual void - traverse_big_float (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "i." << mi.var << "size," << endl - << "i." << mi.var << "indicator == -1);" - << endl; - } - - virtual void - traverse_date (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "i." << mi.var << "indicator == -1);" - << endl; - } - - virtual void - traverse_timestamp (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "i." << mi.var << "indicator == -1);" - << endl; - } - - virtual void - traverse_interval_ym (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "i." << mi.var << "indicator == -1);" - << endl; - } - - virtual void - traverse_interval_ds (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "i." << mi.var << "indicator == -1);" - << endl; - } - - virtual void - traverse_string (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "value," << endl - << "i." << mi.var << "size," << endl - << "i." << mi.var << "indicator == -1);" - << endl; - } - - virtual void - traverse_lob (member_info& mi) - { - os << traits << "::set_value (" << endl - << member << "," << endl - << "i." << mi.var << "callback.callback.result," << endl - << "i." << mi.var << "callback.context.result," << endl - << "i." << mi.var << "indicator == -1);" - << endl; - } - }; - entry<init_value_member> init_value_member_; - - struct container_traits: relational::container_traits, context - { - container_traits (base const& x): base (x) {} - - virtual void - cache_result (string const&) - { - // Caching is not necessary since Oracle can execute several - // interleaving statements. - // - } - - virtual void - init_value_extra () - { - os << "sts.select_statement ().stream_result ();" - << endl; - } - }; - entry<container_traits> container_traits_; - - struct section_traits: relational::section_traits, context - { - section_traits (base const& x): base (x) {} - - virtual void - init_value_extra () - { - os << "st.stream_result ();"; - } - }; - entry<section_traits> section_traits_; - - struct class_: relational::class_, context - { - class_ (base const& x): base (x) {} - - 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& qp, - persist_position p) - { - string r; - - if (p == persist_after_values) - { - data_member_path* id (id_member (c)); - - type* poly_root (polymorphic (c)); - bool poly_derived (poly_root != 0 && poly_root != &c); - - // Top-level auto id. - // - if (id != 0 && !poly_derived && auto_ (*id)) - { - semantics::data_member& idb (*id->back ()); - - const string& name (column_qname (*id)); - const string& type (column_type (idb)); - - r = "RETURNING " + convert_from (name, type, idb) + - " INTO " + qp.next (idb, name, type); - } - } - - return r; - } - - virtual string - select_trailer (type& c) - { - view_query const& vq (c.get<view_query> ("query")); - - if (vq.for_update && vq.distinct) - { - error (vq.loc) - << "Oracle does not support FOR UPDATE with DISTINCT" << endl; - throw operation_failed (); - } - - return base::select_trailer (c); - } - }; - entry<class_> class_entry_; - } - } -} |