aboutsummaryrefslogtreecommitdiff
path: root/odb
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2013-09-16 08:20:00 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2013-09-16 08:20:00 +0200
commitf6eda10b4014ea75af1be88ab3498618e390ea47 (patch)
tree5c91266323a1aeedeb7dc4ab1b0cf2c5c771e66c /odb
parent5a5bf7fc225ac225dbc03df55f6be7c56cb419aa (diff)
Diagnose (potentially) empty UPDATE statements with ROWVERSION
Diffstat (limited to 'odb')
-rw-r--r--odb/common.cxx26
-rw-r--r--odb/common.hxx8
-rw-r--r--odb/relational/mssql/source.cxx33
3 files changed, 63 insertions, 4 deletions
diff --git a/odb/common.cxx b/odb/common.cxx
index 365fe19..f52cee6 100644
--- a/odb/common.cxx
+++ b/odb/common.cxx
@@ -270,12 +270,24 @@ traverse_view (semantics::class_& c)
}
void object_columns_base::
+traverse_pre (semantics::nameable&)
+{
+}
+
+void object_columns_base::
+traverse_post (semantics::nameable&)
+{
+}
+
+void object_columns_base::
traverse (semantics::data_member& m,
semantics::type& t,
std::string const& kp,
std::string const& dn,
semantics::class_* to)
{
+ traverse_pre (m);
+
semantics::class_* oto (context::top_object);
if (to != 0)
@@ -305,6 +317,8 @@ traverse (semantics::data_member& m,
root_ = 0;
context::top_object = oto;
+
+ traverse_post (m);
}
void object_columns_base::
@@ -320,7 +334,10 @@ traverse (semantics::class_& c)
bool f (top_level_);
if (top_level_)
+ {
+ traverse_pre (c);
top_level_ = false;
+ }
else
{
// Unless requested otherwise, don't go into bases if we are a derived
@@ -365,8 +382,13 @@ traverse (semantics::class_& c)
context::top_object = 0;
}
- if (f && !first_)
- flush ();
+ if (f)
+ {
+ if (!first_)
+ flush ();
+
+ traverse_post (c);
+ }
}
void object_columns_base::
diff --git a/odb/common.hxx b/odb/common.hxx
index c4ecbaf..0fcd481 100644
--- a/odb/common.hxx
+++ b/odb/common.hxx
@@ -219,6 +219,14 @@ struct object_columns_base: traversal::class_, virtual context
virtual bool
section_test (data_member_path const&);
+ // Start/end traversal callbacks.
+ //
+ virtual void
+ traverse_pre (semantics::nameable&);
+
+ virtual void
+ traverse_post (semantics::nameable&);
+
public:
object_columns_base (bool first = true,
column_prefix const& cp = column_prefix (),
diff --git a/odb/relational/mssql/source.cxx b/odb/relational/mssql/source.cxx
index 8274b50..83096ab 100644
--- a/odb/relational/mssql/source.cxx
+++ b/odb/relational/mssql/source.cxx
@@ -35,7 +35,8 @@ namespace relational
//
struct object_columns: relational::object_columns, context
{
- object_columns (base const& x): base (x) {}
+ object_columns (base const& x)
+ : base (x), rowversion_ (false), column_count_ (0) {}
virtual bool
column (semantics::data_member& m,
@@ -55,11 +56,39 @@ namespace relational
{
sql_type t (parse_sql_type (column_type (), m));
if (t.type == sql_type::ROWVERSION)
+ {
+ rowversion_ = true;
return false;
+ }
}
- return base::column (m, table, column);
+ 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_;