summaryrefslogtreecommitdiff
path: root/odb/relational/mssql/source.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'odb/relational/mssql/source.cxx')
-rw-r--r--odb/relational/mssql/source.cxx1202
1 files changed, 0 insertions, 1202 deletions
diff --git a/odb/relational/mssql/source.cxx b/odb/relational/mssql/source.cxx
deleted file mode 100644
index dd1e9c8..0000000
--- a/odb/relational/mssql/source.cxx
+++ /dev/null
@@ -1,1202 +0,0 @@
-// file : odb/relational/mssql/source.cxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
-// license : GNU GPL v3; see accompanying LICENSE file
-
-#include <odb/relational/source.hxx>
-
-#include <odb/relational/mssql/common.hxx>
-#include <odb/relational/mssql/context.hxx>
-
-using namespace std;
-
-namespace relational
-{
- namespace mssql
- {
- namespace source
- {
- namespace relational = relational::source;
-
- //
- //
- struct query_parameters: relational::query_parameters
- {
- query_parameters (base const& x): base (x) {}
-
- virtual string
- auto_id (semantics::data_member&, const string&, const string&)
- {
- return "";
- }
- };
- entry<query_parameters> query_parameters_;
-
- //
- //
- struct object_columns: relational::object_columns, context
- {
- object_columns (base const& x)
- : base (x), rowversion_ (false), column_count_ (0) {}
-
- virtual bool
- column (semantics::data_member& m,
- string const& table,
- string const& column)
- {
- // Don't add a column for auto id in the INSERT statement.
- // Only simple, direct id can be auto.
- //
- if (sk_ == statement_insert && key_prefix_.empty () && auto_ (m))
- return false;
-
- // Don't update the ROWVERSION column explicitly.
- //
- if (sk_ == statement_update)
- {
- sql_type t (parse_sql_type (column_type (), m));
- if (t.type == sql_type::ROWVERSION)
- {
- rowversion_ = true;
- return false;
- }
- }
-
- bool r (base::column (m, table, column));
-
- // Count the number of columns in the UPDATE statement, but
- // excluding soft-deleted.
- //
- if (sk_ == statement_update && r && !deleted (member_path_))
- column_count_++;
-
- return r;
- }
-
- virtual void
- traverse_post (semantics::nameable& n)
- {
- if (rowversion_ && column_count_ == 0)
- {
- location l (n.location ());
- error (l) << "ROWVERSION in an object without any readwrite "
- "data members" << endl;
- error (l) << "UPDATE statement will be empty" << endl;
- throw operation_failed ();
- }
- }
-
- private:
- bool rowversion_;
- size_t column_count_;
- };
- entry<object_columns> object_columns_;
-
- //
- //
- struct persist_statement_params: relational::persist_statement_params,
- context
- {
- persist_statement_params (base const& x): base (x) {}
-
- virtual string
- version_value (semantics::data_member& m)
- {
- sql_type t (parse_sql_type (column_type (), m));
- return t.type == sql_type::ROWVERSION ? "DEFAULT" : "1";
- }
- };
- entry<persist_statement_params> persist_statement_params_;
-
- //
- // bind
- //
-
- static const char* integer_buffer_types[] =
- {
- "mssql::bind::bit",
- "mssql::bind::tinyint",
- "mssql::bind::smallint",
- "mssql::bind::int_",
- "mssql::bind::bigint"
- };
-
- struct bind_member: relational::bind_member_impl<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_integer (member_info& mi)
- {
- os << b << ".type = " <<
- integer_buffer_types[mi.st->type - sql_type::BIT] << ";"
- << b << ".buffer = &" << arg << "." << mi.var << "value;"
- << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;";
- }
-
- virtual void
- traverse_decimal (member_info& mi)
- {
- os << b << ".type = mssql::bind::decimal;"
- << b << ".buffer = &" << arg << "." << mi.var << "value;"
- << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;"
- // Encode precision (p) and scale (s) as (p * 100 + s).
- //
- << b << ".capacity = " << mi.st->prec * 100 + mi.st->scale << ";";
- }
-
- virtual void
- traverse_smallmoney (member_info& mi)
- {
- os << b << ".type = mssql::bind::smallmoney;"
- << b << ".buffer = &" << arg << "." << mi.var << "value;"
- << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;";
- }
-
- virtual void
- traverse_money (member_info& mi)
- {
- os << b << ".type = mssql::bind::money;"
- << b << ".buffer = &" << arg << "." << mi.var << "value;"
- << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;";
- }
-
- virtual void
- traverse_float4 (member_info& mi)
- {
- os << b << ".type = mssql::bind::float4;"
- << b << ".buffer = &" << arg << "." << mi.var << "value;"
- << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;"
- << b << ".capacity = " << mi.st->prec << ";";
- }
-
- virtual void
- traverse_float8 (member_info& mi)
- {
- os << b << ".type = mssql::bind::float8;"
- << b << ".buffer = &" << arg << "." << mi.var << "value;"
- << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;"
- << b << ".capacity = " << mi.st->prec << ";";
- }
-
- virtual void
- traverse_string (member_info& mi)
- {
- os << b << ".type = mssql::bind::string;"
- << b << ".buffer = &" << arg << "." << mi.var << "value;"
- << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;"
- << b << ".capacity = static_cast<SQLLEN> (sizeof (" <<
- arg << "." << mi.var << "value));";
- }
-
- virtual void
- traverse_long_string (member_info& mi)
- {
- os << b << ".type = mssql::bind::long_string;"
- << b << ".buffer = &" << arg << "." << mi.var << "callback;"
- << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;"
- // Encode the column size with 0 indicating unlimited.
- //
- << b << ".capacity = " << mi.st->prec << ";";
- }
-
- virtual void
- traverse_nstring (member_info& mi)
- {
- os << b << ".type = mssql::bind::nstring;"
- << b << ".buffer = &" << arg << "." << mi.var << "value;"
- << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;"
- << b << ".capacity = static_cast<SQLLEN> (sizeof (" <<
- arg << "." << mi.var << "value));";
- }
-
- virtual void
- traverse_long_nstring (member_info& mi)
- {
- os << b << ".type = mssql::bind::long_nstring;"
- << b << ".buffer = &" << arg << "." << mi.var << "callback;"
- << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;"
- // Encode the column size (in bytes) with 0 indicating unlimited.
- //
- << b << ".capacity = " << mi.st->prec * 2 << ";";
- }
-
- virtual void
- traverse_binary (member_info& mi)
- {
- os << b << ".type = mssql::bind::binary;"
- << b << ".buffer = &" << arg << "." << mi.var << "value;"
- << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;"
- << b << ".capacity = static_cast<SQLLEN> (sizeof (" <<
- arg << "." << mi.var << "value));";
- }
-
- virtual void
- traverse_long_binary (member_info& mi)
- {
- os << b << ".type = mssql::bind::long_binary;"
- << b << ".buffer = &" << arg << "." << mi.var << "callback;"
- << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;"
- // Encode the column size with 0 indicating unlimited.
- //
- << b << ".capacity = " << mi.st->prec << ";";
- }
-
- virtual void
- traverse_date (member_info& mi)
- {
- os << b << ".type = mssql::bind::date;"
- << b << ".buffer = &" << arg << "." << mi.var << "value;"
- << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;";
- }
-
- virtual void
- traverse_time (member_info& mi)
- {
- os << b << ".type = mssql::bind::time;"
- << b << ".buffer = &" << arg << "." << mi.var << "value;"
- << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;"
- // Encode fractional seconds (scale).
- //
- << b << ".capacity = " << mi.st->scale << ";";
- }
-
- virtual void
- traverse_datetime (member_info& mi)
- {
- unsigned short scale (0);
-
- switch (mi.st->type)
- {
- case sql_type::DATETIME:
- {
- // Looks like it is 3 (rounded to 0.000, 0.003, or 0.007).
- //
- scale = 3;
- break;
- }
- case sql_type::DATETIME2:
- {
- scale = mi.st->scale;
- break;
- }
- case sql_type::SMALLDATETIME:
- {
- // No seconds in SMALLDATATIME. Encode it a special precision
- // value (8).
- //
- scale = 8;
- break;
- }
- default:
- {
- assert (false);
- break;
- }
- }
-
- os << b << ".type = mssql::bind::datetime;"
- << b << ".buffer = &" << arg << "." << mi.var << "value;"
- << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;"
- // Encode fractional seconds (scale).
- //
- << b << ".capacity = " << scale << ";";
- }
-
- virtual void
- traverse_datetimeoffset (member_info& mi)
- {
- os << b << ".type = mssql::bind::datetimeoffset;"
- << b << ".buffer = &" << arg << "." << mi.var << "value;"
- << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;"
- // Encode fractional seconds (scale).
- //
- << b << ".capacity = " << mi.st->scale << ";";
- }
-
- virtual void
- traverse_uniqueidentifier (member_info& mi)
- {
- os << b << ".type = mssql::bind::uniqueidentifier;"
- << b << ".buffer = &" << arg << "." << mi.var << "value;"
- << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;";
- }
-
- virtual void
- traverse_rowversion (member_info& mi)
- {
- os << b << ".type = mssql::bind::rowversion;"
- << b << ".buffer = &" << arg << "." << mi.var << "value;"
- << b << ".size_ind = &" << arg << "." << mi.var << "size_ind;";
- }
- };
- entry<bind_member> 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
- set_null (member_info& mi)
- {
- os << "i." << mi.var << "size_ind = SQL_NULL_DATA;";
- }
-
- virtual void
- check_accessor (member_info& mi, member_access& ma)
- {
- // We cannot use accessors that return by-value for long data
- // members.
- //
- if (long_data (*mi.st) && ma.by_value)
- {
- error (ma.loc) << "accessor returning a value cannot be used "
- << "for a data member of SQL Server long data "
- << "type" << endl;
- info (ma.loc) << "accessor returning a const reference is required"
- << endl;
- info (mi.m.location ()) << "data member is defined here" << endl;
- throw operation_failed ();
- }
- }
-
- virtual void
- traverse_integer (member_info& mi)
- {
- os << traits << "::set_image (" << endl
- << "i." << mi.var << "value, is_null, " << member << ");"
- << "i." << mi.var << "size_ind = is_null ? SQL_NULL_DATA : 0;";
- }
-
- virtual void
- traverse_decimal (member_info& mi)
- {
- os << traits << "::set_image (" << endl
- << "i." << mi.var << "value, is_null, " << member << ");"
- << "i." << mi.var << "size_ind = is_null ? SQL_NULL_DATA : 0;";
- }
-
- virtual void
- traverse_smallmoney (member_info& mi)
- {
- os << traits << "::set_image (" << endl
- << "i." << mi.var << "value, is_null, " << member << ");"
- << "i." << mi.var << "size_ind = is_null ? SQL_NULL_DATA : 4;";
- }
-
- virtual void
- traverse_money (member_info& mi)
- {
- os << traits << "::set_image (" << endl
- << "i." << mi.var << "value, is_null, " << member << ");"
- << "i." << mi.var << "size_ind = is_null ? SQL_NULL_DATA : 8;";
- }
-
- virtual void
- traverse_float4 (member_info& mi)
- {
- os << traits << "::set_image (" << endl
- << "i." << mi.var << "value, is_null, " << member << ");"
- << "i." << mi.var << "size_ind = is_null ? SQL_NULL_DATA : 0;";
- }
-
- virtual void
- traverse_float8 (member_info& mi)
- {
- os << traits << "::set_image (" << endl
- << "i." << mi.var << "value, is_null, " << member << ");"
- << "i." << mi.var << "size_ind = is_null ? SQL_NULL_DATA : 0;";
- }
-
- virtual void
- traverse_string (member_info& mi)
- {
- os << "std::size_t size (0);"
- << traits << "::set_image (" << endl
- << "i." << mi.var << "value," << endl
- // Don't mention the extra character for the null-terminator.
- << "sizeof (i." << mi.var << "value) - 1," << endl
- << "size," << endl
- << "is_null," << endl
- << member << ");"
- << "i." << mi.var << "size_ind =" << endl
- << " is_null ? SQL_NULL_DATA : static_cast<SQLLEN> (size);";
- }
-
- virtual void
- traverse_long_string (member_info& mi)
- {
- os << traits << "::set_image (" << endl
- << "i." << mi.var << "callback.callback.param," << endl
- << "i." << mi.var << "callback.context.param," << endl
- << "is_null," << endl
- << member << ");"
- << "i." << mi.var << "size_ind = is_null ? " <<
- "SQL_NULL_DATA : SQL_DATA_AT_EXEC;";
- }
-
- virtual void
- traverse_nstring (member_info& mi)
- {
- os << "std::size_t size (0);"
- << traits << "::set_image (" << endl
- << "i." << mi.var << "value," << endl
- // Don't mention the extra character for the null-terminator.
- << "sizeof (i." << mi.var << "value) / 2 - 1," << endl
- << "size," << endl
- << "is_null," << endl
- << member << ");"
- << "i." << mi.var << "size_ind =" << endl
- << " is_null ? SQL_NULL_DATA : static_cast<SQLLEN> (size * 2);";
- }
-
- virtual void
- traverse_long_nstring (member_info& mi)
- {
- os << traits << "::set_image (" << endl
- << "i." << mi.var << "callback.callback.param," << endl
- << "i." << mi.var << "callback.context.param," << endl
- << "is_null," << endl
- << member << ");"
- << "i." << mi.var << "size_ind = is_null ? " <<
- "SQL_NULL_DATA : SQL_DATA_AT_EXEC;";
- }
-
- virtual void
- traverse_binary (member_info& mi)
- {
- os << "std::size_t size (0);"
- << traits << "::set_image (" << endl
- << "i." << mi.var << "value," << endl
- << "sizeof (i." << mi.var << "value)," << endl
- << "size," << endl
- << "is_null," << endl
- << member << ");"
- << "i." << mi.var << "size_ind =" << endl
- << " is_null ? SQL_NULL_DATA : static_cast<SQLLEN> (size);";
- }
-
- virtual void
- traverse_long_binary (member_info& mi)
- {
- os << traits << "::set_image (" << endl
- << "i." << mi.var << "callback.callback.param," << endl
- << "i." << mi.var << "callback.context.param," << endl
- << "is_null," << endl
- << member << ");"
- << "i." << mi.var << "size_ind = is_null ? " <<
- "SQL_NULL_DATA : SQL_DATA_AT_EXEC;";
- }
-
- virtual void
- traverse_date (member_info& mi)
- {
- os << traits << "::set_image (" << endl
- << "i." << mi.var << "value, is_null, " << member << ");"
- << "i." << mi.var << "size_ind = is_null ? SQL_NULL_DATA : 0;";
- }
-
- virtual void
- traverse_time (member_info& mi)
- {
- os << traits << "::set_image (" << endl
- << "i." << mi.var << "value, " << mi.st->scale << ", " <<
- "is_null, " << member << ");"
- << "i." << mi.var << "size_ind = is_null" << endl
- << " ? SQL_NULL_DATA" << endl
- << " : static_cast<SQLLEN> (sizeof (i." << mi.var << "value));";
- }
-
- virtual void
- traverse_datetime (member_info& mi)
- {
- // The same code as in bind.
- //
- unsigned short scale (0);
-
- switch (mi.st->type)
- {
- case sql_type::DATETIME:
- {
- scale = 3;
- break;
- }
- case sql_type::DATETIME2:
- {
- scale = mi.st->scale;
- break;
- }
- case sql_type::SMALLDATETIME:
- {
- scale = 8;
- break;
- }
- default:
- {
- assert (false);
- break;
- }
- }
-
- os << traits << "::set_image (" << endl
- << "i." << mi.var << "value, " << scale << ", " <<
- "is_null, " << member << ");"
- << "i." << mi.var << "size_ind = is_null ? SQL_NULL_DATA : 0;";
- }
-
- virtual void
- traverse_datetimeoffset (member_info& mi)
- {
- os << traits << "::set_image (" << endl
- << "i." << mi.var << "value, " << mi.st->scale << ", " <<
- "is_null, " << member << ");"
- << "i." << mi.var << "size_ind = is_null" << endl
- << " ? SQL_NULL_DATA" << endl
- << " : static_cast<SQLLEN> (sizeof (i." << mi.var << "value));";
- }
-
- virtual void
- traverse_uniqueidentifier (member_info& mi)
- {
- os << traits << "::set_image (" << endl
- << "i." << mi.var << "value, is_null, " << member << ");"
- << "i." << mi.var << "size_ind = is_null ? SQL_NULL_DATA : 0;";
- }
-
- virtual void
- traverse_rowversion (member_info& mi)
- {
- os << traits << "::set_image (" << endl
- << "i." << mi.var << "value, is_null, " << member << ");"
- << "i." << mi.var << "size_ind = is_null ? SQL_NULL_DATA : 8;";
- }
- };
- entry<init_image_member> init_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 << "size_ind == SQL_NULL_DATA";
- }
-
- virtual void
- check_modifier (member_info& mi, member_access& ma)
- {
- // We cannot use by-value modifier for long data members.
- //
- if (long_data (*mi.st) && ma.placeholder ())
- {
- error (ma.loc) << "modifier accepting a value cannot be used "
- << "for a data member of SQL Server long data "
- << "type" << endl;
- info (ma.loc) << "modifier returning a non-const reference is "
- << "required" << endl;
- info (mi.m.location ()) << "data member is defined here" << endl;
- throw operation_failed ();
- }
- }
-
- virtual void
- traverse_integer (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "size_ind == SQL_NULL_DATA);"
- << endl;
- }
-
- virtual void
- traverse_decimal (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "size_ind == SQL_NULL_DATA);"
- << endl;
- }
-
- virtual void
- traverse_smallmoney (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "size_ind == SQL_NULL_DATA);"
- << endl;
- }
-
- virtual void
- traverse_money (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "size_ind == SQL_NULL_DATA);"
- << endl;
- }
-
- virtual void
- traverse_float4 (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "size_ind == SQL_NULL_DATA);"
- << endl;
- }
-
- virtual void
- traverse_float8 (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "size_ind == SQL_NULL_DATA);"
- << endl;
- }
-
- virtual void
- traverse_string (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "static_cast<std::size_t> (i." << mi.var << "size_ind)," << endl
- << "i." << mi.var << "size_ind == SQL_NULL_DATA);"
- << endl;
- }
-
- virtual void
- traverse_long_string (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "callback.callback.result," << endl
- << "i." << mi.var << "callback.context.result);"
- << endl;
- }
-
- virtual void
- traverse_nstring (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "static_cast<std::size_t> (" <<
- "i." << mi.var << "size_ind / 2)," << endl
- << "i." << mi.var << "size_ind == SQL_NULL_DATA);"
- << endl;
- }
-
- virtual void
- traverse_long_nstring (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "callback.callback.result," << endl
- << "i." << mi.var << "callback.context.result);"
- << endl;
- }
-
- virtual void
- traverse_binary (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "static_cast<std::size_t> (i." << mi.var << "size_ind)," << endl
- << "i." << mi.var << "size_ind == SQL_NULL_DATA);"
- << endl;
- }
-
- virtual void
- traverse_long_binary (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "callback.callback.result," << endl
- << "i." << mi.var << "callback.context.result);"
- << endl;
- }
-
- virtual void
- traverse_date (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "size_ind == SQL_NULL_DATA);"
- << endl;
- }
-
- virtual void
- traverse_time (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "size_ind == SQL_NULL_DATA);"
- << endl;
- }
-
- virtual void
- traverse_datetime (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "size_ind == SQL_NULL_DATA);"
- << endl;
- }
-
- virtual void
- traverse_datetimeoffset (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "size_ind == SQL_NULL_DATA);"
- << endl;
- }
-
- virtual void
- traverse_uniqueidentifier (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "size_ind == SQL_NULL_DATA);"
- << endl;
- }
-
- virtual void
- traverse_rowversion (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "size_ind == SQL_NULL_DATA);"
- << endl;
- }
- };
- entry<init_value_member> init_value_member_;
-
- struct statement_columns_common: context
- {
- void
- process (relational::statement_columns& cols,
- statement_kind sk,
- bool dynamic)
- {
- using relational::statement_columns;
-
- // Long data columns must come last in the SELECT statement. If
- // this statement is going to be processed at runtime, then this
- // will be taken care of then.
- //
- if (sk != statement_select || dynamic)
- return;
-
- // Go over the columns list while keeping track of how many
- // columns we have examined. If the current column is long data,
- // then move it to the back. Stop once we have examined all the
- // columns.
- //
- size_t n (cols.size ());
- for (statement_columns::iterator i (cols.begin ()); n != 0; --n)
- {
- if (long_data (parse_sql_type (i->type, *i->member)))
- {
- cols.push_back (*i);
- i = cols.erase (i);
- }
- else
- ++i;
- }
- }
- };
-
- struct container_traits: relational::container_traits,
- statement_columns_common
- {
- container_traits (base const& x): base (x) {}
-
- virtual void
- cache_result (string const&)
- {
- // Caching is not necessary since with MARS enabled SQL Server
- // can execute several interleaving statements.
- //
- }
-
- virtual void
- init_value_extra ()
- {
- os << "sts.select_statement ().stream_result ();"
- << endl;
- }
-
- virtual void
- process_statement_columns (relational::statement_columns& cols,
- statement_kind sk,
- bool dynamic)
- {
- statement_columns_common::process (cols, sk, dynamic);
- }
- };
- entry<container_traits> container_traits_;
-
- struct section_traits: relational::section_traits,
- statement_columns_common
- {
- section_traits (base const& x): base (x) {}
-
- virtual void
- init_value_extra ()
- {
- os << "st.stream_result ();";
- }
-
- virtual void
- process_statement_columns (relational::statement_columns& cols,
- statement_kind sk,
- bool dynamic)
- {
- statement_columns_common::process (cols, sk, dynamic);
- }
-
- virtual string
- optimistic_version_increment (semantics::data_member& m)
- {
- sql_type t (parse_sql_type (column_type (m), m));
- return t.type != sql_type::ROWVERSION
- ? "1"
- : "version (sts.id_image ())";
- }
-
- virtual string
- update_statement_extra (user_section&)
- {
- string r;
-
- semantics::data_member* ver (optimistic (c_));
-
- if (ver == 0 ||
- parse_sql_type (column_type (*ver), *ver).type !=
- sql_type::ROWVERSION)
- return r;
-
- // ROWVERSION & SQL Server 2005 incompatibility is detected
- // in persist_statement_extra.
- //
- r = "OUTPUT INSERTED." +
- convert_from (column_qname (*ver, column_prefix ()), *ver);
-
- return r;
- }
- };
- entry<section_traits> section_traits_;
-
- struct class_: relational::class_, statement_columns_common
- {
- class_ (base const& x):
- base (x), init_version_value_member_id_image_ ("v", "version_") {}
-
- virtual void
- init_image_pre (type& c)
- {
- if (options.generate_query () &&
- !(composite (c) || (abstract (c) && !polymorphic (c))))
- {
- type* poly_root (polymorphic (c));
- bool poly_derived (poly_root != 0 && poly_root != &c);
-
- if (poly_derived)
- os << "{"
- << "root_traits::image_type& ri (root_image (i));"
- << endl;
-
- string i (poly_derived ? "ri" : "i");
-
- os << "if (" << i << ".change_callback_.callback != 0)" << endl
- << "(" << i << ".change_callback_.callback) (" <<
- i << ".change_callback_.context);";
-
- if (poly_derived)
- os << "}";
- else
- os << endl;
- }
- }
-
- virtual void
- init_value_extra ()
- {
- os << "st.stream_result ();";
- }
-
- virtual string
- persist_statement_extra (type& c,
- relational::query_parameters&,
- persist_position p)
- {
- string r;
-
- type* poly_root (polymorphic (c));
- bool poly_derived (poly_root != 0 && poly_root != &c);
-
- // If we are a derived type in a polymorphic hierarchy, then
- // auto id/version are handled by the root.
- //
- if (poly_derived)
- return r;
-
- // See if we have auto id or ROWVERSION version.
- //
- data_member_path* id (id_member (c));
- semantics::data_member* ver (optimistic (c));
-
- if (id != 0 && !auto_ (*id))
- id = 0;
-
- if (ver != 0)
- {
- sql_type t (parse_sql_type (column_type (*ver), *ver));
- if (t.type != sql_type::ROWVERSION)
- ver = 0;
- }
-
- if (id == 0 && ver == 0)
- return r;
-
- // SQL Server 2005 has a bug that causes it to fail on an
- // INSERT statement with the OUTPUT clause if data for one
- // of the inserted columns is supplied at execution (long
- // data). To work around this problem we use the less
- // efficient batch of INSERT and SELECT statements.
- //
- if (options.mssql_server_version () <= mssql_version (9, 0))
- {
- bool ld (false);
-
- if (c.count ("mssql-has-long-data"))
- ld = c.get<bool> ("mssql-has-long-data");
- else
- {
- has_long_data t (ld);
- t.traverse (c);
- c.set ("mssql-has-long-data", ld);
- }
-
- if (ld)
- {
- if (p == persist_after_values)
- {
- // SQL Server 2005 has no eqivalent of SCOPE_IDENTITY for
- // ROWVERSION.
- //
- if (ver != 0)
- {
- error (c.location ()) << "in SQL Server 2005 ROWVERSION " <<
- "value cannot be retrieved for a persistent class " <<
- "containing long data" << endl;
- throw operation_failed ();
- }
-
- // We also cannot support bulk INSERT.
- //
- if (c.count ("bulk-persist"))
- {
- error (c.location ()) << "in SQL Server 2005 bulk " <<
- "persist operation cannot be implemented for a " <<
- "persistent class containing long data" << endl;
- throw operation_failed ();
- }
-
- r = "; SELECT " +
- convert_from ("SCOPE_IDENTITY()", *id->back ());
- }
-
- return r;
- }
- }
-
- if (p == persist_after_columns)
- {
- r = "OUTPUT ";
-
- // Top-level auto id column.
- //
- if (id != 0)
- r += "INSERTED." +
- convert_from (column_qname (*id), *id->back ());
-
- // Top-level version column.
- //
- if (ver != 0)
- {
- if (id != 0)
- r += ',';
-
- r += "INSERTED." + convert_from (
- column_qname (*ver, column_prefix ()), *ver);
- }
- }
-
- return r;
- }
-
- virtual string
- update_statement_extra (type& c)
- {
- string r;
-
- type* poly_root (polymorphic (c));
- bool poly_derived (poly_root != 0 && poly_root != &c);
-
- // If we are a derived type in a polymorphic hierarchy, then
- // version is handled by the root.
- //
- if (poly_derived)
- return r;
-
- semantics::data_member* ver (optimistic (c));
-
- if (ver == 0 ||
- parse_sql_type (column_type (*ver), *ver).type !=
- sql_type::ROWVERSION)
- return r;
-
- // Long data & SQL Server 2005 incompatibility is detected
- // in persist_statement_extra.
- //
- r = "OUTPUT INSERTED." +
- convert_from (column_qname (*ver, column_prefix ()), *ver);
-
- return r;
- }
-
- virtual void
- process_statement_columns (relational::statement_columns& cols,
- statement_kind sk,
- bool dynamic)
- {
- statement_columns_common::process (cols, sk, dynamic);
- }
-
- virtual string
- optimistic_version_init (semantics::data_member& m, bool index)
- {
- sql_type t (parse_sql_type (column_type (m), m));
- return t.type != sql_type::ROWVERSION
- ? "1"
- : (index
- ? "version (sts.id_image (i))"
- : "version (sts.id_image ())");
- }
-
- virtual string
- optimistic_version_increment (semantics::data_member& m, bool index)
- {
- sql_type t (parse_sql_type (column_type (m), m));
- return t.type != sql_type::ROWVERSION
- ? "1"
- : (index
- ? "version (sts.id_image (i))"
- : "version (sts.id_image ())");
- }
-
- virtual bool
- optimistic_insert_bind_version (semantics::data_member& m)
- {
- sql_type t (parse_sql_type (column_type (m), m));
- return t.type == sql_type::ROWVERSION;
- }
-
- virtual void
- object_extra (type& c)
- {
- bool abst (abstract (c));
-
- type* poly_root (polymorphic (c));
- bool poly (poly_root != 0);
- bool poly_derived (poly && poly_root != &c);
-
- if (poly_derived || (abst && !poly))
- return;
-
- if (semantics::data_member* m = optimistic (c))
- {
- sql_type t (parse_sql_type (column_type (*m), *m));
- if (t.type == sql_type::ROWVERSION)
- {
- string const& type (class_fq_name (c));
- string traits ("access::object_traits_impl< " + type + ", id_" +
- db.string () + " >");
-
- os << traits << "::version_type" << endl
- << traits << "::" << endl
- << "version (const id_image_type& i)"
- << "{"
- << "version_type v;";
- init_version_value_member_id_image_->traverse (*m);
- os << "return v;"
- << "}";
- }
- }
- }
-
- virtual string
- from_trailer (type& c)
- {
- return c.get<view_query> ("query").for_update
- ? " WITH (UPDLOCK)"
- : "";
- }
-
- virtual string
- select_trailer (type&) {return "";}
-
- private:
- // Go via the dynamic creation to get access to the constructor.
- //
- instance<relational::init_value_member>
- init_version_value_member_id_image_;
- };
- entry<class_> class_entry_;
- }
- }
-}