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/oracle/context.cxx | 795 -------------------------------------- 1 file changed, 795 deletions(-) delete mode 100644 odb/relational/oracle/context.cxx (limited to 'odb/relational/oracle/context.cxx') 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 -#include - -#include -#include - -#include - -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 (root_context::data_.get ()), m), - data_ (static_cast (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 (&t)) - { - semantics::type& bt (a->base_type ()); - if (bt.is_a ()) - { - unsigned long long n (a->size ()); - - if (n == 0) - return r; - else if (n == 1) - r = "CHAR"; - else - { - r = "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") : 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 (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); - } - } - } -} -- cgit v1.1