summaryrefslogtreecommitdiff
path: root/odb/relational/validator.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'odb/relational/validator.cxx')
-rw-r--r--odb/relational/validator.cxx639
1 files changed, 0 insertions, 639 deletions
diff --git a/odb/relational/validator.cxx b/odb/relational/validator.cxx
deleted file mode 100644
index 9bebcf0..0000000
--- a/odb/relational/validator.cxx
+++ /dev/null
@@ -1,639 +0,0 @@
-// file : odb/relational/validator.cxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
-// license : GNU GPL v3; see accompanying LICENSE file
-
-#include <map>
-#include <iostream>
-
-#include <odb/diagnostics.hxx>
-#include <odb/traversal.hxx>
-#include <odb/relational/common.hxx>
-#include <odb/relational/context.hxx>
-#include <odb/relational/validator.hxx>
-
-using namespace std;
-
-namespace relational
-{
- 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 (null (m))
- {
- if (semantics::class_* c = composite_wrapper (utype (m)))
- {
- if (has_a (*c, test_container))
- {
- os << m.file () << ":" << m.line () << ":" << m.column () << ":"
- << " error: composite member containing containers cannot "
- << "be null" << endl;
-
- os << c->file () << ":" << c->line () << ":" << c->column ()
- << ": info: composite value type is defined here" << endl;
-
- valid_ = false;
- }
- }
- }
-
- // Check on-delete.
- //
- if (m.count ("on-delete"))
- {
- const char* kp (container (m) ? "value" : "");
- location l (m.location ());
-
- // Make sure it is a pointer or a member with points_to pragma.
- //
- if (!object_pointer (utype (m, kp)) && !points_to (m))
- {
- error (l) << "on_delete specified for non-object pointer" << endl;
- valid_ = false;
- }
-
- // Make sure it is not inverse.
- //
- if (inverse (m, kp))
- {
- error (l) << "on_delete specified for inverse object " <<
- "pointer" << endl;
- valid_ = false;
- }
-
- // Make sure the pointer is nullable if asked to set it to NULL.
- //
- using sema_rel::foreign_key;
-
- if (m.get<foreign_key::action_type> ("on-delete") ==
- foreign_key::set_null &&
- !null (m, kp))
- {
- error (l) << "set_null specified for non-nullable object "
- "pointer" << endl;
- valid_ = false;
- }
- }
- }
-
- bool& valid_;
- };
-
- struct object_no_id_members: object_members_base
- {
- object_no_id_members (bool& valid)
- : object_members_base (false, false, true), valid_ (valid), dm_ (0)
- {
- }
-
- virtual void
- traverse_pointer (semantics::data_member& m, semantics::class_&)
- {
- if (inverse (m))
- {
- semantics::data_member& dm (dm_ != 0 ? *dm_ : m);
-
- os << dm.file () << ":" << dm.line () << ":" << dm.column () << ":"
- << " error: inverse object pointer member '" << member_prefix_
- << m.name () << "' in an object without an object id" << endl;
-
- valid_ = false;
- }
- }
-
- virtual void
- traverse_container (semantics::data_member& m, semantics::type&)
- {
- semantics::data_member& dm (dm_ != 0 ? *dm_ : m);
-
- os << dm.file () << ":" << dm.line () << ":" << dm.column () << ":"
- << " error: container member '" << member_prefix_ << m.name ()
- << "' in an object without an object id" << endl;
-
- valid_ = false;
- }
-
- virtual void
- traverse_composite (semantics::data_member* m, semantics::class_& c)
- {
- semantics::data_member* old_dm (dm_);
-
- if (dm_ == 0)
- dm_ = m;
-
- object_members_base::traverse_composite (m, c);
-
- dm_ = old_dm;
- }
-
- private:
- bool& valid_;
- semantics::data_member* dm_; // Direct object data member.
- };
-
- struct composite_id_members: object_members_base
- {
- composite_id_members (bool& valid)
- : object_members_base (false, false, true), valid_ (valid), dm_ (0)
- {
- }
-
- virtual void
- traverse_pointer (semantics::data_member& m, semantics::class_&)
- {
- semantics::data_member& dm (dm_ != 0 ? *dm_ : m);
-
- os << dm.file () << ":" << dm.line () << ":" << dm.column () << ":"
- << " error: object pointer member '" << member_prefix_ << m.name ()
- << "' in a composite value type that is used as an object id"
- << endl;
-
- valid_ = false;
- }
-
- virtual void
- traverse_simple (semantics::data_member& m)
- {
- if (readonly (member_path_, member_scope_))
- {
- semantics::data_member& dm (dm_ != 0 ? *dm_ : m);
-
- os << dm.file () << ":" << dm.line () << ":" << dm.column () << ":"
- << " error: readonly member '" << member_prefix_ << m.name ()
- << "' in a composite value type that is used as an object id"
- << endl;
-
- valid_ = false;
- }
- }
-
- virtual void
- traverse_container (semantics::data_member& m, semantics::type&)
- {
- semantics::data_member& dm (dm_ != 0 ? *dm_ : m);
-
- os << dm.file () << ":" << dm.line () << ":" << dm.column () << ":"
- << " error: container member '" << member_prefix_ << m.name ()
- << "' in a composite value type that is used as an object id"
- << endl;
-
- valid_ = false;
- }
-
- virtual void
- traverse_composite (semantics::data_member* m, semantics::class_& c)
- {
- semantics::data_member* old_dm (dm_);
-
- if (dm_ == 0)
- dm_ = m;
-
- object_members_base::traverse_composite (m, c);
-
- dm_ = old_dm;
- }
-
- private:
- bool& valid_;
- semantics::data_member* dm_; // Direct composite member.
- };
-
- struct view_members: object_members_base
- {
- view_members (bool& valid)
- : object_members_base (false, false, true), valid_ (valid), dm_ (0)
- {
- }
-
- virtual void
- traverse_pointer (semantics::data_member& m, semantics::class_&)
- {
- if (dm_ != 0 && object_pointer (utype (m)))
- {
- location const& l (dm_->location ());
-
- error (l) << "nested view data member '" << member_prefix_
- << m.name () << "' is an object pointer" << endl;
- info (l) << "views can only contain direct object pointer members"
- << endl;
-
- valid_ = false;
- }
- }
-
- virtual void
- traverse_container (semantics::data_member& m, semantics::type&)
- {
- semantics::data_member& dm (dm_ != 0 ? *dm_ : m);
-
- os << dm.file () << ":" << dm.line () << ":" << dm.column () << ":"
- << " error: view data member '" << member_prefix_ << m.name ()
- << "' is a container" << endl;
-
- os << dm.file () << ":" << dm.line () << ":" << dm.column () << ":"
- << ": info: views cannot contain containers" << endl;
-
- valid_ = false;
- }
-
- virtual void
- traverse_composite (semantics::data_member* m, semantics::class_& c)
- {
- semantics::data_member* old_dm (dm_);
-
- if (dm_ == 0)
- dm_ = m;
-
- object_members_base::traverse_composite (m, c);
-
- dm_ = old_dm;
- }
-
- private:
- bool& valid_;
- semantics::data_member* dm_; // Direct view data member.
- };
-
- struct class2: traversal::class_, context
- {
- class2 (bool& valid)
- : valid_ (valid),
- typedefs_ (true),
- data_member_ (valid),
- object_no_id_members_ (valid),
- composite_id_members_ (valid),
- view_members_ (valid)
- {
- *this >> defines_ >> *this;
- *this >> typedefs_ >> *this;
-
- data_member_names_ >> data_member_;
- }
-
- virtual void
- traverse (type& c)
- {
- class_kind_type ck (class_kind (c));
- switch (ck)
- {
- case class_object:
- names (c);
- traverse_object (c);
- break;
- case class_view:
- names (c);
- traverse_view (c);
- break;
- case class_composite:
- names (c);
- traverse_composite (c);
- break;
- case class_other:
- break;
- }
-
- // Make sure indexes are not defined for anything other than objects.
- //
- if (c.count ("index") && ck != class_object)
- {
- indexes& ins (c.get<indexes> ("index"));
-
- for (indexes::iterator i (ins.begin ()); i != ins.end (); ++i)
- {
- error (i->loc) << "index definition on a non-persistent class"
- << endl;
- valid_ = false;
- }
- }
- }
-
- virtual void
- traverse_object (type& c)
- {
- data_member_path* id (id_member (c));
-
- if (id != 0)
- {
- if (semantics::class_* cm = composite_wrapper (utype (*id)))
- {
- location idl (id->front ()->location ());
-
- // Composite id cannot be auto.
- //
- if (auto_ (*id))
- {
- error (idl) << "composite id cannot be automatically assigned"
- << endl;
- valid_ = false;
- }
-
- // Make sure we don't have any containers or pointers in this
- // composite value type.
- //
- if (valid_)
- {
- composite_id_members_.traverse (*cm);
-
- if (!valid_)
- info (idl) << "composite id is defined here" << endl;
- }
-
- // Check that the composite value type is default-constructible.
- //
- if (!cm->default_ctor ())
- {
- os << cm->file () << ":" << cm->line () << ":" << cm->column ()
- << ": error: composite value type that is used as object id "
- << "is not default-constructible" << endl;
-
- os << cm->file () << ":" << cm->line () << ":" << cm->column ()
- << ": info: provide default constructor for this value type"
- << endl;
-
- info (idl) << "composite id is defined here" << endl;
-
- valid_ = false;
- }
- }
- }
- else
- {
- if (!abstract (c))
- {
- // Make sure we don't have any containers or inverse pointers.
- //
- object_no_id_members_.traverse (c);
- }
- }
-
- names (c, data_member_names_);
-
- // Validate bulk operation support.
- //
- for (bool i (true); i && c.count ("bulk"); i = false)
- {
- location_t l (c.get<location_t> ("bulk-location"));
-
- if (polymorphic (c))
- {
- error (l) << "bulk operations on polymorphic objects are "
- "not supported" << endl;
- valid_ = false;
- break;
- }
-
- if (has_a (c, test_straight_container))
- {
- error (l) << "bulk operations on objects with containers are "
- "not supported" << endl;
- valid_ = false;
- break;
- }
-
- bool update (true);
-
- // Unless we only have manually-updated sections, we cannot generate
- // the bulk update operation.
- //
- user_sections& uss (c.get<user_sections> ("user-sections"));
-
- for (user_sections::iterator i (uss.begin ());
- update && i != uss.end ();
- ++i)
- {
- const user_section& s (*i);
-
- // Skip special sections.
- //
- if (s.special != user_section::special_ordinary)
- continue;
-
- // Always-updated section still needs a separate statement
- // (since it may not be loaded).
- //
- if (!s.update_empty () && s.update != user_section::update_manual)
- update = false;
- }
-
- c.set ("bulk-persist", true);
- if (update) c.set ("bulk-update", true);
- c.set ("bulk-erase", true);
- }
-
- // Validate indexes.
- //
- {
- indexes& ins (c.get<indexes> ("index"));
-
- // Make sure index members are not transient, inverse, or
- // containers.
- //
- for (indexes::iterator i (ins.begin ()); i != ins.end (); ++i)
- {
- index& in (*i);
-
- for (index::members_type::iterator i (in.members.begin ());
- i != in.members.end (); ++i)
- {
- index::member& im (*i);
- semantics::data_member& m (*im.path.back ());
-
- if (transient (m))
- {
- error (im.loc) << "index member is transient" << endl;
- valid_ = false;
- }
-
- if (inverse (m))
- {
- error (im.loc) << "index member is an inverse object " <<
- "pointer" << endl;
- valid_ = false;
- }
-
- if (container (m))
- {
- error (im.loc) << "index member is a container" << endl;
- valid_ = false;
- }
- }
- }
- }
- }
-
- virtual void
- traverse_view (type& c)
- {
- const view_query& vq (c.get<view_query> ("query"));
-
- // Make sure we don't have any containers or object pointers.
- //
- view_members_.traverse (c);
-
- names (c, data_member_names_);
-
- // Allow certain kinds of empty views.
- //
- if (vq.kind != view_query::runtime &&
- vq.kind != view_query::complete_execute)
- {
- // Allow all the members to be deleted.
- //
- column_count_type const& cc (column_count (c));
-
- if (cc.total == 0)
- {
- os << c.file () << ":" << c.line () << ":" << c.column () << ":"
- << " error: no persistent data members in the class" << endl;
- valid_ = false;
- }
- }
- }
-
- virtual void
- traverse_composite (type& c)
- {
- names (c, data_member_names_);
- }
-
- public:
- bool& valid_;
-
- traversal::defines defines_;
- typedefs typedefs_;
-
- data_member2 data_member_;
- traversal::names data_member_names_;
-
- object_no_id_members object_no_id_members_;
- composite_id_members composite_id_members_;
- view_members view_members_;
- };
- }
-
- void
- validate (options const&,
- features&,
- semantics::unit& u,
- semantics::path const&,
- unsigned short pass)
- {
- bool valid (true);
-
- // Validate custom type mapping.
- //
- if (pass == 1)
- {
- // Create an empty list if we don't have one. This makes the
- // rest of the code simpler.
- //
- if (!u.count ("custom-db-types"))
- u.set ("custom-db-types", custom_db_types ());
-
- custom_db_types & cts (u.get<custom_db_types> ("custom-db-types"));
-
- for (custom_db_types::iterator i (cts.begin ()); i != cts.end (); ++i)
- {
- custom_db_type& ct (*i);
-
- if (ct.type.empty ())
- {
- error (ct.loc) << "'type' clause expected in db pragma map" << endl;
- valid = false;
- }
-
- if (ct.as.empty ())
- {
- error (ct.loc) << "'as' clause expected in db pragma map" << endl;
- valid = false;
- }
-
- if (ct.to.empty ())
- ct.to = "(?)";
- else
- {
- size_t p (ct.to.find ("(?)"));
-
- if (p == string::npos)
- {
- error (ct.loc) << "no '(?)' expression in the 'to' clause "
- << "of db pragma map" << endl;
- valid = false;
- }
- else if (ct.to.find ("(?)", p + 3) != string::npos)
- {
- error (ct.loc) << "multiple '(?)' expressions in the 'to' "
- << "clause of db pragma map" << endl;
- valid = false;
- }
- }
-
- if (ct.from.empty ())
- ct.from = "(?)";
- else
- {
- size_t p (ct.from.find ("(?)"));
-
- if (p == string::npos)
- {
- error (ct.loc) << "no '(?)' expression in the 'from' clause "
- << "of db pragma map" << endl;
- valid = false;
- }
- else if (ct.from.find ("(?)", p + 3) != string::npos)
- {
- error (ct.loc) << "multiple '(?)' expressions in the 'from' "
- << "clause of db pragma map" << endl;
- valid = false;
- }
- }
- }
- }
-
- if (!valid)
- throw operation_failed ();
-
- if (pass == 1)
- {
- }
- else
- {
- traversal::unit unit;
- traversal::defines unit_defines;
- typedefs unit_typedefs (true);
- traversal::namespace_ ns;
- class2 c (valid);
-
- unit >> unit_defines >> ns;
- unit_defines >> c;
- unit >> unit_typedefs >> c;
-
- traversal::defines ns_defines;
- typedefs ns_typedefs (true);
-
- ns >> ns_defines >> ns;
- ns_defines >> c;
- ns >> ns_typedefs >> c;
-
- unit.dispatch (u);
- }
-
- if (!valid)
- throw operation_failed ();
- }
-}