From 648f94540c67f84fdba6b5097323b89f6c914292 Mon Sep 17 00:00:00 2001 From: Constantin Michael Date: Thu, 6 Oct 2011 09:03:27 +0200 Subject: Add common implementation for Oracle --- odb/makefile | 3 +- odb/relational/oracle/common.cxx | 453 +++++++++++++++++++++++++++++++++++++++ odb/relational/oracle/common.hxx | 252 ++++++++++++++++++++++ 3 files changed, 707 insertions(+), 1 deletion(-) create mode 100644 odb/relational/oracle/common.cxx create mode 100644 odb/relational/oracle/common.hxx (limited to 'odb') diff --git a/odb/makefile b/odb/makefile index c90ac88..a415b44 100644 --- a/odb/makefile +++ b/odb/makefile @@ -53,9 +53,10 @@ relational/mysql/header.cxx \ relational/mysql/source.cxx \ relational/mysql/schema.cxx -# +# Relational/Oracle # cxx_ptun += \ +relational/oracle/common.cxx \ relational/oracle/context.cxx # Relational/PostgreSQL diff --git a/odb/relational/oracle/common.cxx b/odb/relational/oracle/common.cxx new file mode 100644 index 0000000..f77f391 --- /dev/null +++ b/odb/relational/oracle/common.cxx @@ -0,0 +1,453 @@ +// file : odb/relational/oracle/common.cxx +// author : Constantin Michael +// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +// license : ODB NCUEL; see accompanying LICENSE file + +#include + +#include + +using namespace std; + +namespace relational +{ + namespace oracle + { + static bool + unsigned_integer (semantics::type& t) + { + const string& s (t.name ()); + + return s == "bool" || + s == "unsigned char" || + s == "short unsigned int" || + s == "unsigned int" || + s == "long unsigned int" || + s == "long long unsigned int"; + } + + // + // member_base + // + + void member_base:: + traverse (semantics::data_member& m) + { + if (transient (m)) + return; + + string var; + + if (!var_override_.empty ()) + var = var_override_; + else + { + string const& name (m.name ()); + var = name + (name[name.size () - 1] == '_' ? "" : "_"); + } + + semantics::type& t (type_override_ != 0 ? *type_override_ : m.type ()); + + if (semantics::class_* c = composite_wrapper (t)) + { + // If t is a wrapper, pass the wrapped type. Also pass the + // original, wrapper type. + // + member_info mi (m, *c, (wrapper (t) ? &t : 0), var, fq_type_override_); + if (pre (mi)) + { + traverse_composite (mi); + post (mi); + } + } + else if (semantics::type* c = container_wrapper (t)) + { + // The same unwrapping logic as for composite values. + // + member_info mi (m, *c, (wrapper (t) ? &t : 0), var, fq_type_override_); + if (pre (mi)) + { + traverse_container (mi); + post (mi); + } + } + else + { + sql_type const& st (column_sql_type (m, key_prefix_)); + + if (semantics::class_* c = object_pointer (t)) + { + member_info mi ( + m, id_member (*c)->type (), 0, var, fq_type_override_); + mi.st = &st; + if (pre (mi)) + { + traverse_object_pointer (mi); + post (mi); + } + } + else + { + member_info mi (m, t, 0, var, fq_type_override_); + mi.st = &st; + if (pre (mi)) + { + traverse_simple (mi); + post (mi); + } + } + } + } + + 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.range) + { + unsigned short r (st.range_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 ().ver_major () > 11 || + (options.oracle_client_version ().ver_major () == 11 && + options.oracle_client_version ().ver_minor () >= 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 = r - s, where r is the range, 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 + 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->range_value <= 24) + traverse_float (mi); + else if (mi.st->range_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; + } + // 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 (semantics::type* type, + string const& fq_type, + string const& key_prefix) + : relational::member_base (type, fq_type, key_prefix) + { + } + + string member_image_type:: + image_type (semantics::data_member& m) + { + type_.clear (); + member_base::traverse (m); + return type_; + } + + void member_image_type:: + traverse_composite (member_info& mi) + { + type_ = "composite_value_traits< " + mi.fq_type () + " >::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_ = "char*"; + } + + void member_image_type:: + traverse_string (member_info&) + { + type_ = "char*"; + } + + void member_image_type:: + traverse_lob (member_info&) + { + type_ = "oracle::lob_callback"; + } + + // + // 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 (semantics::type* type, + string const& fq_type, + string const& key_prefix) + : relational::member_base (type, fq_type, key_prefix) + { + } + + string member_database_type_id:: + database_type_id (type& m) + { + type_id_.clear (); + member_base::traverse (m); + 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_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]; + } + + // + // query_columns + // + + struct query_columns: relational::query_columns, context + { + query_columns (base const& x): base (x) {} + + virtual string + database_type_id (semantics::data_member& m) + { + return member_database_type_id_.database_type_id (m); + } + + private: + member_database_type_id member_database_type_id_; + }; + entry query_columns_; + } +} diff --git a/odb/relational/oracle/common.hxx b/odb/relational/oracle/common.hxx new file mode 100644 index 0000000..f41e9d6 --- /dev/null +++ b/odb/relational/oracle/common.hxx @@ -0,0 +1,252 @@ +// file : odb/relational/oracle/common.hxx +// author : Constantin Michael +// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +// license : ODB NCUEL; see accompanying LICENSE file + +#ifndef ODB_RELATIONAL_ORACLE_COMMON_HXX +#define ODB_RELATIONAL_ORACLE_COMMON_HXX + +#include +#include + +namespace relational +{ + namespace oracle + { + struct member_base: virtual relational::member_base, context + { + member_base (base const& x): base (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. + // + member_base () {} + + virtual void + traverse (semantics::data_member& m); + + struct member_info + { + semantics::data_member& m; // Member. + semantics::type& t; // Member C++ type (m.type () may != t). + semantics::type* wrapper; // Wrapper type if member is a wrapper. + // In this case t is the wrapped type. + sql_type const* st; // Member SQL type (only simple values). + string& var; // Member variable name with trailing '_'. + + // C++ type fq-name. + // + string + fq_type (bool unwrap = true) const + { + if (wrapper != 0 && unwrap) + { + // Use the hint from the wrapper. + // + return t.fq_name ( + wrapper->get ("wrapper-hint")); + } + + // Use the original type from 'm' instead of 't' since the hint + // may be invalid for a different type. Plus, if a type is + // overriden, then the fq_type must be as well. + // + return fq_type_.empty () + ? m.type ().fq_name (m.belongs ().hint ()) + : fq_type_; + } + + string const& fq_type_; + + member_info (semantics::data_member& m_, + semantics::type& t_, + semantics::type* wrapper_, + string& var_, + string const& fq_type) + : m (m_), + t (t_), + wrapper (wrapper_), + st (0), + var (var_), + fq_type_ (fq_type) + { + } + }; + + // The false return value indicates that no further callbacks + // should be called for this member. + // + virtual bool + pre (member_info&) + { + return true; + } + + virtual void + post (member_info&) + { + } + + virtual void + traverse_composite (member_info&) + { + } + + virtual void + traverse_container (member_info&) + { + } + + virtual void + traverse_object_pointer (member_info& mi) + { + traverse_simple (mi); + } + + 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_string (member_info&) + { + } + + virtual void + traverse_lob (member_info&) + { + } + }; + + struct member_image_type: member_base + { + member_image_type (semantics::type* type = 0, + string const& fq_type = string (), + string const& key_prefix = string ()); + 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_string (member_info&); + + virtual void + traverse_lob (member_info&); + + private: + string type_; + }; + + struct member_database_type_id: member_base + { + member_database_type_id (semantics::type* type = 0, + string const& fq_type = string (), + string const& key_prefix = string ()); + 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_string (member_info&); + + virtual void + traverse_lob (member_info&); + + private: + string type_id_; + }; + } +} +#endif // ODB_RELATIONAL_ORACLE_COMMON_HXX -- cgit v1.1