aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--odb/context.cxx6
-rw-r--r--odb/context.hxx12
-rw-r--r--odb/processor.cxx64
-rw-r--r--odb/relational/mysql/source.cxx36
-rw-r--r--odb/relational/pgsql/source.cxx36
-rw-r--r--odb/relational/source.hxx85
-rw-r--r--odb/relational/sqlite/source.cxx36
-rw-r--r--odb/validator.cxx72
8 files changed, 279 insertions, 68 deletions
diff --git a/odb/context.cxx b/odb/context.cxx
index bbde65a..4db15a0 100644
--- a/odb/context.cxx
+++ b/odb/context.cxx
@@ -2425,6 +2425,12 @@ namespace
dv = 0;
}
+ if (av != 0)
+ c_.added++;
+
+ if (dv != 0)
+ c_.deleted++;
+
if (av != 0 || dv != 0)
c_.soft++;
}
diff --git a/odb/context.hxx b/odb/context.hxx
index f188a41..e0238dd 100644
--- a/odb/context.hxx
+++ b/odb/context.hxx
@@ -797,6 +797,12 @@ public:
// Return the addition version or 0 if not soft-added.
//
static unsigned long long
+ added (semantics::class_& c) // Used for composite only.
+ {
+ return c.get<unsigned long long> ("added", 0);
+ }
+
+ static unsigned long long
added (semantics::data_member& m)
{
return m.get<unsigned long long> ("added", 0);
@@ -1235,6 +1241,8 @@ public:
readonly (0),
optimistic_managed (0),
discriminator (0),
+ added (0),
+ deleted (0),
soft (0),
separate_load (0),
separate_update (0)
@@ -1248,7 +1256,9 @@ public:
size_t optimistic_managed;
size_t discriminator;
- size_t soft; // Soft-added/deleted.
+ size_t added; // Soft-added.
+ size_t deleted; // Soft-deleted.
+ size_t soft; // Soft-added/deleted (a column can be both).
size_t separate_load;
size_t separate_update; // Only readwrite.
diff --git a/odb/processor.cxx b/odb/processor.cxx
index 0bb9796..6730242 100644
--- a/odb/processor.cxx
+++ b/odb/processor.cxx
@@ -1955,6 +1955,53 @@ namespace
tree container_traits_;
};
+ // Figure out the "summary" added/deleted version for a composite
+ // value type.
+ //
+ struct summary_version: object_members_base
+ {
+ summary_version (): av (0), dv (0), a_ (true), d_ (true) {}
+
+ virtual void
+ traverse_simple (semantics::data_member&)
+ {
+ if (a_)
+ {
+ if (unsigned long long v = added (member_path_))
+ {
+ if (av == 0 || av < v)
+ av = v;
+ }
+ else
+ {
+ av = 0;
+ a_ = false;
+ }
+ }
+
+ if (d_)
+ {
+ if (unsigned long long v = deleted (member_path_))
+ {
+ if (dv == 0 || dv > v)
+ dv = v;
+ }
+ else
+ {
+ dv = 0;
+ d_ = false;
+ }
+ }
+ }
+
+ public:
+ unsigned long long av;
+ unsigned long long dv;
+
+ bool a_;
+ bool d_;
+ };
+
struct class_: traversal::class_, context
{
class_ ()
@@ -2449,7 +2496,24 @@ namespace
// Figure out if we are versioned.
//
if (force_versioned || column_count (c).soft != 0)
+ {
c.set ("versioned", true);
+
+ // See if we are "summarily" added/deleted, that is, all the
+ // columns are added/deleted. Note: this does not include
+ // containers.
+ //
+ summary_version sv;
+ sv.traverse (c);
+
+ // Note: there are no locations.
+ //
+ if (sv.av != 0)
+ c.set ("added", sv.av);
+
+ if (sv.dv != 0)
+ c.set ("deleted", sv.dv);
+ }
}
//
diff --git a/odb/relational/mysql/source.cxx b/odb/relational/mysql/source.cxx
index df7f19c..0df66db 100644
--- a/odb/relational/mysql/source.cxx
+++ b/odb/relational/mysql/source.cxx
@@ -331,11 +331,28 @@ namespace relational
os << "// " << mi.m.name () << endl
<< "//" << endl;
+ semantics::class_* comp (composite (mi.t));
+
// If the member is soft- added or deleted, check the version.
//
unsigned long long av (added (mi.m));
unsigned long long dv (deleted (mi.m));
+ // If this is a composite member, see if it is summarily
+ // added/deleted.
+ //
+ if (comp != 0)
+ {
+ unsigned long long cav (added (*comp));
+ unsigned long long cdv (deleted (*comp));
+
+ if (cav != 0 && (av == 0 || av < cav))
+ av = cav;
+
+ if (cdv != 0 && (dv == 0 || dv > cdv))
+ dv = cdv;
+ }
+
// If the addition/deletion version is the same as the section's,
// then we don't need the test.
//
@@ -372,10 +389,25 @@ namespace relational
virtual void
post (member_info& mi)
{
+ semantics::class_* comp (composite (mi.t));
+
if (var_override_.empty ())
{
unsigned long long av (added (mi.m));
unsigned long long dv (deleted (mi.m));
+
+ if (comp != 0)
+ {
+ unsigned long long cav (added (*comp));
+ unsigned long long cdv (deleted (*comp));
+
+ if (cav != 0 && (av == 0 || av < cav))
+ av = cav;
+
+ if (cdv != 0 && (dv == 0 || dv > cdv))
+ dv = cdv;
+ }
+
if (user_section* s = dynamic_cast<user_section*> (section_))
{
if (av == added (*s->member))
@@ -389,8 +421,8 @@ namespace relational
os << "}";
}
- if (semantics::class_* c = composite (mi.t))
- index_ += column_count (*c).total;
+ if (comp != 0)
+ index_ += column_count (*comp).total;
else
index_++;
}
diff --git a/odb/relational/pgsql/source.cxx b/odb/relational/pgsql/source.cxx
index a287dd2..b625524 100644
--- a/odb/relational/pgsql/source.cxx
+++ b/odb/relational/pgsql/source.cxx
@@ -308,11 +308,28 @@ namespace relational
os << "// " << mi.m.name () << endl
<< "//" << endl;
+ semantics::class_* comp (composite (mi.t));
+
// If the member is soft- added or deleted, check the version.
//
unsigned long long av (added (mi.m));
unsigned long long dv (deleted (mi.m));
+ // If this is a composite member, see if it is summarily
+ // added/deleted.
+ //
+ if (comp != 0)
+ {
+ unsigned long long cav (added (*comp));
+ unsigned long long cdv (deleted (*comp));
+
+ if (cav != 0 && (av == 0 || av < cav))
+ av = cav;
+
+ if (cdv != 0 && (dv == 0 || dv > cdv))
+ dv = cdv;
+ }
+
// If the addition/deletion version is the same as the section's,
// then we don't need the test.
//
@@ -349,10 +366,25 @@ namespace relational
virtual void
post (member_info& mi)
{
+ semantics::class_* comp (composite (mi.t));
+
if (var_override_.empty ())
{
unsigned long long av (added (mi.m));
unsigned long long dv (deleted (mi.m));
+
+ if (comp != 0)
+ {
+ unsigned long long cav (added (*comp));
+ unsigned long long cdv (deleted (*comp));
+
+ if (cav != 0 && (av == 0 || av < cav))
+ av = cav;
+
+ if (cdv != 0 && (dv == 0 || dv > cdv))
+ dv = cdv;
+ }
+
if (user_section* s = dynamic_cast<user_section*> (section_))
{
if (av == added (*s->member))
@@ -366,8 +398,8 @@ namespace relational
os << "}";
}
- if (semantics::class_* c = composite (mi.t))
- index_ += column_count (*c).total;
+ if (comp != 0)
+ index_ += column_count (*comp).total;
else
index_++;
}
diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx
index 642c5ac..ded4781 100644
--- a/odb/relational/source.hxx
+++ b/odb/relational/source.hxx
@@ -984,6 +984,8 @@ namespace relational
if (section_ == 0 && separate_load (mi.m) && inverse (mi.m))
return false;
+ semantics::class_* comp (composite (mi.t));
+
os << "// " << mi.m.name () << endl
<< "//" << endl;
@@ -1003,11 +1005,9 @@ namespace relational
//
else if (!readonly (*context::top_object))
{
- semantics::class_* c;
-
if (id (mi.m) ||
readonly (mi.m) ||
- ((c = composite (mi.t)) && readonly (*c)) ||
+ (comp != 0 && readonly (*comp)) ||
(section_ == 0 && separate_update (mi.m)))
os << "if (sk != statement_update)"
<< "{";
@@ -1018,6 +1018,21 @@ namespace relational
unsigned long long av (added (mi.m));
unsigned long long dv (deleted (mi.m));
+ // If this is a composite member, see if it is summarily
+ // added/deleted.
+ //
+ if (comp != 0)
+ {
+ unsigned long long cav (added (*comp));
+ unsigned long long cdv (deleted (*comp));
+
+ if (cav != 0 && (av == 0 || av < cav))
+ av = cav;
+
+ if (cdv != 0 && (dv == 0 || dv > cdv))
+ dv = cdv;
+ }
+
// If the addition/deletion version is the same as the section's,
// then we don't need the test.
//
@@ -1056,11 +1071,26 @@ namespace relational
{
if (var_override_.empty ())
{
+ semantics::class_* comp (composite (mi.t));
+
// We need to increment the index even if we skipped this
// member due to the schema version.
//
unsigned long long av (added (mi.m));
unsigned long long dv (deleted (mi.m));
+
+ if (comp != 0)
+ {
+ unsigned long long cav (added (*comp));
+ unsigned long long cdv (deleted (*comp));
+
+ if (cav != 0 && (av == 0 || av < cav))
+ av = cav;
+
+ if (cdv != 0 && (dv == 0 || dv > cdv))
+ dv = cdv;
+ }
+
if (user_section* s = dynamic_cast<user_section*> (section_))
{
if (av == added (*s->member))
@@ -1073,10 +1103,10 @@ namespace relational
if (av != 0 || dv != 0)
os << "}";
- if (semantics::class_* c = composite (mi.t))
+ if (comp != 0)
{
- bool ro (readonly (*c));
- column_count_type const& cc (column_count (*c));
+ bool ro (readonly (*comp));
+ column_count_type const& cc (column_count (*comp));
os << "n += " << cc.total << "UL";
@@ -1391,6 +1421,21 @@ namespace relational
unsigned long long av (added (mi.m));
unsigned long long dv (deleted (mi.m));
+ // If this is a composite member, see if it is summarily
+ // added/deleted.
+ //
+ if (comp != 0)
+ {
+ unsigned long long cav (added (*comp));
+ unsigned long long cdv (deleted (*comp));
+
+ if (cav != 0 && (av == 0 || av < cav))
+ av = cav;
+
+ if (cdv != 0 && (dv == 0 || dv > cdv))
+ dv = cdv;
+ }
+
// If the addition/deletion version is the same as the section's,
// then we don't need the test.
//
@@ -1609,6 +1654,19 @@ namespace relational
{
unsigned long long av (added (mi.m));
unsigned long long dv (deleted (mi.m));
+
+ if (comp != 0)
+ {
+ unsigned long long cav (added (*comp));
+ unsigned long long cdv (deleted (*comp));
+
+ if (cav != 0 && (av == 0 || av < cav))
+ av = cav;
+
+ if (cdv != 0 && (dv == 0 || dv > cdv))
+ dv = cdv;
+ }
+
if (user_section* s = dynamic_cast<user_section*> (section_))
{
if (av == added (*s->member))
@@ -1806,6 +1864,21 @@ namespace relational
unsigned long long av (added (mi.m));
unsigned long long dv (deleted (mi.m));
+ // If this is a composite member, see if it is summarily
+ // added/deleted.
+ //
+ if (comp != 0)
+ {
+ unsigned long long cav (added (*comp));
+ unsigned long long cdv (deleted (*comp));
+
+ if (cav != 0 && (av == 0 || av < cav))
+ av = cav;
+
+ if (cdv != 0 && (dv == 0 || dv > cdv))
+ dv = cdv;
+ }
+
// If the addition/deletion version is the same as the section's,
// then we don't need the test.
//
diff --git a/odb/relational/sqlite/source.cxx b/odb/relational/sqlite/source.cxx
index 09b5de7..78bee1d 100644
--- a/odb/relational/sqlite/source.cxx
+++ b/odb/relational/sqlite/source.cxx
@@ -108,11 +108,28 @@ namespace relational
os << "// " << mi.m.name () << endl
<< "//" << endl;
+ semantics::class_* comp (composite (mi.t));
+
// If the member is soft- added or deleted, check the version.
//
unsigned long long av (added (mi.m));
unsigned long long dv (deleted (mi.m));
+ // If this is a composite member, see if it is summarily
+ // added/deleted.
+ //
+ if (comp != 0)
+ {
+ unsigned long long cav (added (*comp));
+ unsigned long long cdv (deleted (*comp));
+
+ if (cav != 0 && (av == 0 || av < cav))
+ av = cav;
+
+ if (cdv != 0 && (dv == 0 || dv > cdv))
+ dv = cdv;
+ }
+
// If the addition/deletion version is the same as the section's,
// then we don't need the test.
//
@@ -149,10 +166,25 @@ namespace relational
virtual void
post (member_info& mi)
{
+ semantics::class_* comp (composite (mi.t));
+
if (var_override_.empty ())
{
unsigned long long av (added (mi.m));
unsigned long long dv (deleted (mi.m));
+
+ if (comp != 0)
+ {
+ unsigned long long cav (added (*comp));
+ unsigned long long cdv (deleted (*comp));
+
+ if (cav != 0 && (av == 0 || av < cav))
+ av = cav;
+
+ if (cdv != 0 && (dv == 0 || dv > cdv))
+ dv = cdv;
+ }
+
if (user_section* s = dynamic_cast<user_section*> (section_))
{
if (av == added (*s->member))
@@ -166,8 +198,8 @@ namespace relational
os << "}";
}
- if (semantics::class_* c = composite (mi.t))
- index_ += column_count (*c).total;
+ if (comp != 0)
+ index_ += column_count (*comp).total;
else
index_++;
}
diff --git a/odb/validator.cxx b/odb/validator.cxx
index 1a025a0..2de8882 100644
--- a/odb/validator.cxx
+++ b/odb/validator.cxx
@@ -1016,24 +1016,6 @@ namespace
// Pass 2.
//
- struct data_member2: traversal::data_member, context
- {
- data_member2 (bool& valid): valid_ (valid) {}
-
- virtual void
- traverse (type& m)
- {
- if (transient (m))
- return;
-
- if (!deleted (m)) // Don't include deleted members in the count.
- count_++;
- }
-
- bool& valid_;
- size_t count_;
- };
-
// Make sure soft-delete versions make sense for dependent entities.
// We don't seem to need anything for soft-add since if an entity is
// not added (e.g., an object), then we cannot reference it in the
@@ -1198,7 +1180,7 @@ namespace
struct class2: traversal::class_, context
{
class2 (bool& valid)
- : valid_ (valid), has_lt_operator_ (0), member_ (valid)
+ : valid_ (valid), has_lt_operator_ (0)
{
// Find the has_lt_operator function template.
//
@@ -1236,8 +1218,6 @@ namespace
if (has_lt_operator_ == 0)
valid_ = false;
-
- *this >> names_ >> member_;
}
virtual void
@@ -1261,21 +1241,13 @@ namespace
virtual void
traverse_object (type& c)
{
- bool base (false);
- for (type::inherits_iterator i (c.inherits_begin ());
- !base && i != c.inherits_end ();
- ++i)
- {
- if (object (i->base ()))
- base = true;
- }
-
+ bool abst (abstract (c));
bool poly (polymorphic (c));
// Make sure we have no empty or pointless sections unless we
// are reuse-abstract or polymorphic.
//
- if (!poly && !abstract (c))
+ if (!poly && !abst)
{
user_sections& uss (c.get<user_sections> ("user-sections"));
@@ -1394,12 +1366,15 @@ namespace
}
}
- // Check members.
+ // Allow all the members to be deleted as long as there is no
+ // schema for this class.
//
- member_.count_ = 0;
- names (c);
+ column_count_type const& cc (column_count (c));
+ size_t cont (has_a (c, test_container));
+ size_t dcont (cont - has_a (c, test_container | exclude_deleted));
- if (member_.count_ == 0 && !base)
+ if ((cc.total == 0 && cont == 0) ||
+ (cc.total == cc.deleted && cont == dcont && !(abst || deleted (c))))
{
os << c.file () << ":" << c.line () << ":" << c.column () << ":"
<< " error: no persistent data members in the class" << endl;
@@ -1410,12 +1385,11 @@ namespace
virtual void
traverse_view (type& c)
{
- // Check members.
+ // Allow all the members to be deleted.
//
- member_.count_ = 0;
- names (c);
+ column_count_type const& cc (column_count (c));
- if (member_.count_ == 0)
+ if (cc.total == 0)
{
os << c.file () << ":" << c.line () << ":" << c.column () << ":"
<< " error: no persistent data members in the class" << endl;
@@ -1426,21 +1400,12 @@ namespace
virtual void
traverse_composite (type& c)
{
- bool base (false);
- for (type::inherits_iterator i (c.inherits_begin ());
- !base && i != c.inherits_end ();
- ++i)
- {
- if (composite (i->base ()))
- base = true;
- }
-
- // Check members.
+ // Allow all the members to be deleted.
//
- member_.count_ = 0;
- names (c);
+ column_count_type const& cc (column_count (c));
+ size_t cont (has_a (c, test_container));
- if (member_.count_ == 0 && !base)
+ if (cc.total == 0 && cont == 0)
{
os << c.file () << ":" << c.line () << ":" << c.column () << ":"
<< " error: no persistent data members in the class" << endl;
@@ -1450,9 +1415,6 @@ namespace
bool& valid_;
tree has_lt_operator_;
-
- data_member2 member_;
- traversal::names names_;
};
}