From c29c8d56300d2b834b5e3dac998a893877b7c902 Mon Sep 17 00:00:00 2001 From: Constantin Michael Date: Fri, 7 Oct 2011 14:24:03 +0200 Subject: Add Oracle header and source implementations --- odb/relational/oracle/header.cxx | 176 +++++++++ odb/relational/oracle/source.cxx | 765 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 941 insertions(+) create mode 100644 odb/relational/oracle/header.cxx create mode 100644 odb/relational/oracle/source.cxx (limited to 'odb/relational/oracle') diff --git a/odb/relational/oracle/header.cxx b/odb/relational/oracle/header.cxx new file mode 100644 index 0000000..fa0f12f --- /dev/null +++ b/odb/relational/oracle/header.cxx @@ -0,0 +1,176 @@ +// file : odb/relational/oracle/header.cxx +// author : Constantin Michael +// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +// license : GNU GPL v3; see accompanying LICENSE file + +#include + +#include +#include + +namespace relational +{ + namespace oracle + { + namespace header + { + namespace relational = relational::header; + + struct image_member: relational::image_member, member_base + { + image_member (base const& x) + : member_base::base (x), // virtual base + base (x), + member_base (x), + member_image_type_ (base::type_override_, + base::fq_type_override_, + base::key_prefix_) + { + } + + virtual bool + pre (member_info& mi) + { + if (container (mi.t)) + return false; + + image_type = member_image_type_.image_type (mi.m); + + if (var_override_.empty ()) + os << "// " << mi.m.name () << endl + << "//" << endl; + + return true; + } + + virtual void + traverse_composite (member_info& mi) + { + os << image_type << " " << mi.var << "value;" + << endl; + } + + 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->range) + n = mi.st->range_value / 2 + mi.st->range_value % 2; + + // We require an additional 2 bytes for length and exponent fields. + // + 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) + { + 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) + { + // @@ Need to calculate the length of the array based on the + // member_info range. + // + os << "char " << mi.var << "value[11];" + << "ub2 " << mi.var << "size;" + << "sb2 " << mi.var << "indicator;" + << endl; + } + + virtual void + traverse_string (member_info& mi) + { + size_t n (mi.st->range ? mi.st->range_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. + // Assume the database character set uses a single byte fixed width + // encoding. + // + if ((mi.st->type == sql_type::NCHAR || + mi.st->type == sql_type::NVARCHAR2) && !mi.st->byte_semantics) + n *= 4; + + os << "char " << mi.var << "value[" << n << "];" + << "ub2 " << mi.var << "size;" + << "sb2 " << mi.var << "indicator;" + << endl; + } + + virtual void + traverse_lob (member_info& mi) + { + os << image_type << " " << mi.var << "callback;" + << "sb2 " << mi.var << "indicator;" + << "OCILobLocator* " << mi.var << "lob;" + << "void* " << mi.var << "context;" + << "ub4 " << mi.var << "position_context;" + << "char " << mi.var << "buffer[4096];" + << endl; + } + + private: + string image_type; + + member_image_type member_image_type_; + }; + entry image_member_; + } + } +} diff --git a/odb/relational/oracle/source.cxx b/odb/relational/oracle/source.cxx new file mode 100644 index 0000000..bca1d30 --- /dev/null +++ b/odb/relational/oracle/source.cxx @@ -0,0 +1,765 @@ +// file : odb/relational/oracle/source.cxx +// author : Constantin Michael +// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +// license : GNU GPL v3; see accompanying LICENSE file + +#include + +#include + +#include +#include + +using namespace std; + +namespace relational +{ + namespace oracle + { + namespace source + { + namespace relational = relational::source; + + struct query_parameters: relational::query_parameters + { + query_parameters (base const& x) + : base (x), + i_ (0) + { + } + + virtual string + next () + { + ostringstream ss; + ss << ":" << ++i_; + + return ss.str (); + } + + private: + size_t i_; + }; + entry 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::string" // RAW + }; + + const char* lob_buffer_types[] = + { + "oracle::bind::blob", + "oracle::bind::clob", + "oracle::bind::nclob" + }; + } + + // + // bind + // + + struct bind_member: relational::bind_member, member_base + { + bind_member (base const& x) + : member_base::base (x), // virtual base + base (x), + member_base (x) + { + } + + virtual bool + pre (member_info& mi) + { + if (container (mi.t)) + return false; + + ostringstream ostr; + ostr << "b[n]"; + b = ostr.str (); + + arg = arg_override_.empty () ? string ("i") : arg_override_; + + if (var_override_.empty ()) + { + os << "// " << mi.m.name () << endl + << "//" << endl; + + if (inverse (mi.m, key_prefix_)) + os << "if (out)" + << "{"; + } + + return true; + } + + virtual void + post (member_info& mi) + { + if (var_override_.empty ()) + { + if (semantics::class_* c = composite (mi.t)) + os << "n += " << in_column_count (*c) << "UL;"; + else + os << "n++;"; + + if (inverse (mi.m, key_prefix_)) + os << "}"; + else + os << endl; + } + } + + virtual void + traverse_composite (member_info& mi) + { + os << "composite_value_traits< " << mi.fq_type () << + " >::bind (b + n, " << arg << "." << mi.var << "value);"; + } + + 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 = " << arg << "." << mi.var << + "static_cast (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 (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 (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 << ".capacity = static_cast (sizeof (" << arg << "." << + mi.var << "value));" + << b << ".size = &" << arg << "." << mi.var << "size;" + << 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 = " << arg << "." << mi.var << + "static_cast (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 << ".indicator = &" << arg << "." << mi.var << "indicator;" + << b << ".size = " << "out ?" << endl + << "reinterpret_cast (&" << arg << "." << mi.var << + "lob) :" << endl + << "reinterpret_cast (&" << arg << "." << mi.var << + "position_context);" + << b << ".callback_context = " << arg << "." << mi.var << + "context;" + << b << ".buffer = " << arg << "." << mi.var << "buffer;" + << b << ".capacity = static_cast (sizeof (" << arg << "." << + mi.var << "buffer));" + << endl; + } + + private: + string b; + string arg; + }; + entry bind_member_; + + // + // init image + // + + struct init_image_member: relational::init_image_member, member_base + { + init_image_member (base const& x) + : member_base::base (x), // virtual base + base (x), + member_base (x), + member_database_type_id_ (base::type_override_, + base::fq_type_override_, + base::key_prefix_) + { + } + + virtual bool + pre (member_info& mi) + { + // Ignore containers (they get their own table) and inverse + // object pointers (they are not present in the 'in' binding). + // + if (container (mi.t) || inverse (mi.m, key_prefix_)) + return false; + + if (!member_override_.empty ()) + member = member_override_; + else + { + string const& name (mi.m.name ()); + member = "o." + name; + + os << "// " << name << endl + << "//" << endl; + } + + // If this is a wrapped composite value, then we need to + // "unwrap" it. For simple values this is taken care of + // by the value_traits specializations. + // + if (mi.wrapper != 0 && composite (mi.t)) + { + // Here we need the wrapper type, not the wrapped type. + // + member = "wrapper_traits< " + mi.fq_type (false) + " >::" + + "get_ref (" + member + ")"; + } + + if (composite (mi.t)) + traits = "composite_value_traits< " + mi.fq_type () + " >"; + else + { + // When handling a pointer, mi.t is the id type of the referenced + // object. + // + semantics::type& mt (member_type (mi.m, key_prefix_)); + + if (semantics::class_* c = object_pointer (mt)) + { + type = "obj_traits::id_type"; + db_type_id = member_database_type_id_.database_type_id (mi.m); + + // Handle NULL pointers and extract the id. + // + os << "{" + << "typedef object_traits< " << c->fq_name () << + " > obj_traits;"; + + if (weak_pointer (mt)) + { + os << "typedef pointer_traits< " << mi.fq_type () << + " > wptr_traits;" + << "typedef pointer_traits< wptr_traits::" << + "strong_pointer_type > ptr_traits;" + << endl + << "wptr_traits::strong_pointer_type sp (" << + "wptr_traits::lock (" << member << "));"; + + member = "sp"; + } + else + os << "typedef pointer_traits< " << mi.fq_type () << + " > ptr_traits;" + << endl; + + os << "bool is_null (ptr_traits::null_ptr (" << member << "));" + << "if (!is_null)" + << "{" + << "const " << type << "& id (" << endl; + + if (lazy_pointer (mt)) + os << "ptr_traits::object_id< ptr_traits::element_type > (" << + member << ")"; + else + os << "obj_traits::id (ptr_traits::get_ref (" << member << "))"; + + os << ");" + << endl; + + member = "id"; + } + else + { + type = mi.fq_type (); + db_type_id = member_database_type_id_.database_type_id (mi.m); + + os << "{" + << "bool is_null;"; + } + + traits = "oracle::value_traits<\n " + + type + ",\n " + + db_type_id + " >"; + } + + return true; + } + + virtual void + post (member_info& mi) + { + if (!composite (mi.t)) + { + // When handling a pointer, mi.t is the id type of the referenced + // object. + // + if (object_pointer (member_type (mi.m, key_prefix_))) + { + os << "}"; + + if (!null (mi.m, key_prefix_)) + os << "else" << endl + << "throw null_pointer ();"; + } + + os << "i." << mi.var << "indicator = is_null ? -1 : 0;" + << "}"; + } + } + + virtual void + traverse_composite (member_info& mi) + { + os << traits << "init (" << endl + << "i." << mi.var << "value," << endl + << member << ");"; + } + + virtual void + traverse_int32 (member_info& mi) + { + os << traits << "::set_image (" << endl + << "i." << mi.var << "value, is_null, " << member << ");"; + } + + virtual void + traverse_int64 (member_info& mi) + { + os << traits << "::set_image (" << endl + << "i." << mi.var << "value, is_null, " << member << ");"; + } + + virtual void + traverse_big_int (member_info& mi) + { + os << "std::size_t size (0);" + << traits << "::set_image (" << endl + << "i." << mi.var << "value," << endl + << "sizeof (i." << mi.var << "value)," << endl + << "size," << endl + << "is_null," << endl + << member << ");" + << "i." << mi.var << "size = static_cast (size);"; + } + + virtual void + traverse_float (member_info& mi) + { + os << traits << "::set_image (" << endl + << "i." << mi.var << "value, is_null, " << member << ");"; + } + + virtual void + traverse_double (member_info& mi) + { + os << traits << "::set_image (" << endl + << "i." << mi.var << "value, is_null, " << member << ");"; + } + + 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 << "size = static_cast (size);"; + } + + virtual void + traverse_date (member_info& mi) + { + os << traits << "::set_image (" << endl + << "i." << mi.var << "value, is_null, " << member << ");"; + } + + virtual void + traverse_timestamp (member_info& mi) + { + os << "std::size_t size (0);" + << traits << "::set_image (" << endl + << "i." << mi.var << "value," << endl + << "sizeof (i." << mi.var << "value)," << endl + << "size," << endl + << "is_null," << endl + << member << ");" + << "i." << mi.var << "size = static_cast (size);"; + } + + 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 << "size = static_cast (size);"; + } + + virtual void + traverse_lob (member_info& mi) + { + os << traits << "::set_image (" << endl + << "i." << mi.var << "callback.param," << endl + << "i." << mi.var << "context," << endl + << "is_null," << endl + << member << ");"; + } + + private: + string type; + string db_type_id; + string member; + string traits; + + member_database_type_id member_database_type_id_; + }; + entry init_image_member_; + + // + // init value + // + + struct init_value_member: relational::init_value_member, member_base + { + init_value_member (base const& x) + : member_base::base (x), // virtual base + base (x), + member_base (x), + member_database_type_id_ (base::type_override_, + base::fq_type_override_, + base::key_prefix_) + { + } + + virtual bool + pre (member_info& mi) + { + if (container (mi.t)) + return false; + + if (!member_override_.empty ()) + member = member_override_; + else + { + string const& name (mi.m.name ()); + member = "o." + name; + + os << "// " << name << endl + << "//" << endl; + } + + // If this is a wrapped composite value, then we need to + // "unwrap" it. For simple values this is taken care of + // by the value_traits specializations. + // + if (mi.wrapper != 0 && composite (mi.t)) + { + // Here we need the wrapper type, not the wrapped type. + // + member = "wrapper_traits< " + mi.fq_type (false) + " >::" + + "set_ref (" + member + ")"; + } + + if (composite (mi.t)) + traits = "composite_value_traits< " + mi.fq_type () + " >"; + else + { + // When handling a pointer, mi.t is the id type of the referenced + // object. + // + semantics::type& mt (member_type (mi.m, key_prefix_)); + + if (semantics::class_* c = object_pointer (mt)) + { + type = "obj_traits::id_type"; + db_type_id = member_database_type_id_.database_type_id (mi.m); + + // Handle NULL pointers and extract the id. + // @@ Check the null logic with boris. + // + os << "{" + << "typedef object_traits< " << c->fq_name () << + " > obj_traits;" + << "typedef pointer_traits< " << mi.fq_type () << + " > ptr_traits;" + << endl + << "if (i." << mi.var << "indicator == -1)" << endl; + + if (null (mi.m, key_prefix_)) + os << member << " = ptr_traits::pointer_type ();"; + else + os << "throw null_pointer ();"; + + os << "else" + << "{" + << type << " id;"; + + member = "id"; + } + else + { + type = mi.fq_type (); + db_type_id = member_database_type_id_.database_type_id (mi.m); + + os << "i." << mi.var << "indicator = is_null ? -1 : 0;" + << "}"; + + os << "{" + << "bool is_null (i. " << mi.var << "indicator == -1);"; + } + + traits = "oracle::value_traits<\n " + + type + ",\n " + + db_type_id + " >"; + } + + return true; + } + + virtual void + post (member_info& mi) + { + if (composite (mi.t)) + return; + + // When handling a pointer, mi.t is the id type of the referenced + // object. + // + semantics::type& mt (member_type (mi.m, key_prefix_)); + + if (object_pointer (mt)) + { + member = member_override_.empty () + ? "o." + mi.m.name () + : member_override_; + + if (lazy_pointer (mt)) + os << member << " = ptr_traits::pointer_type (db, id);"; + else + os << "// If a compiler error points to the line below, then" << endl + << "// it most likely means that a pointer used in a member" << endl + << "// cannot be initialized from an object pointer." << endl + << "//" << endl + << member << " = ptr_traits::pointer_type (" << endl + << "db.load< obj_traits::object_type > (id));"; + + os << "}" + << "}"; + } + } + + virtual void + traverse_composite (member_info& mi) + { + os << traits << "::init (" << endl + << member << "," << endl + << "i." << mi.var << "value," << endl + << "db);" + << endl; + } + + virtual void + traverse_int32 (member_info& mi) + { + os << traits << "::set_value (" << endl + << member << ", i." << mi.var << "value, is_null);" + << endl; + } + + virtual void + traverse_int64 (member_info& mi) + { + os << traits << "::set_value (" << endl + << member << ", i." << mi.var << "value, is_null);" + << 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 + << "is_null);" + << endl; + } + + virtual void + traverse_float (member_info& mi) + { + os << traits << "::set_value (" << endl + << member << ", i." << mi.var << "value, is_null);" + << endl; + } + + virtual void + traverse_double (member_info& mi) + { + os << traits << "::set_value (" << endl + << member << ", i." << mi.var << "value, is_null)" + << 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 + << "is_null);" + << endl; + } + + virtual void + traverse_date (member_info& mi) + { + os << traits << "::set_value (" << endl + << member << ", i." << mi.var << "value, is_null);" + << endl; + } + + virtual void + traverse_timestamp (member_info& mi) + { + os << traits << "::set_value (" << endl + << member << "," << endl + << "i." << mi.var << "value," << endl + << "i." << mi.var << "size," << endl + << "is_null);" + << 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 + << "is_null);" + << endl; + } + + virtual void + traverse_lob (member_info& mi) + { + os << traits << "::set_value (" << endl + << member << "," << endl + << "i." << mi.var << "callback.result," << endl + << "i." << mi.var << "context," << endl + << "is_null);" + << endl; + } + + private: + string type; + string db_type_id; + string traits; + string member; + + member_database_type_id member_database_type_id_; + }; + entry init_value_member_; + + struct class_: relational::class_, context + { + class_ (base const& x): base (x) {} + + virtual void + init_auto_id (semantics::data_member&, string const& im) + { + os << im << "value = 0;"; + } + }; + entry class_entry_; + } + } +} -- cgit v1.1