From af12ffe836de09ec84f666effa4df347eeb07a43 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 26 Jan 2012 12:43:16 +0200 Subject: Implement support for database schema New pragma qualifier: namespace. New pragma specifier: schema. The table specifier was extended to accept a schema prefix. New option: --default- schema. The common/schema test was extended to cover the new functionality. --- odb/semantics/namespace.cxx | 3 +- odb/semantics/namespace.hxx | 22 +++++ odb/semantics/relational/column.cxx | 2 +- odb/semantics/relational/column.hxx | 6 +- odb/semantics/relational/elements.cxx | 106 +++++++--------------- odb/semantics/relational/elements.hxx | 88 ++++++++++++------- odb/semantics/relational/elements.txx | 94 ++++++++++++++++++++ odb/semantics/relational/foreign-key.cxx | 1 + odb/semantics/relational/foreign-key.hxx | 10 +-- odb/semantics/relational/index.cxx | 1 + odb/semantics/relational/index.hxx | 5 +- odb/semantics/relational/key.cxx | 2 +- odb/semantics/relational/key.hxx | 10 +-- odb/semantics/relational/model.cxx | 2 +- odb/semantics/relational/model.hxx | 6 +- odb/semantics/relational/name.cxx | 95 ++++++++++++++++++++ odb/semantics/relational/name.hxx | 146 +++++++++++++++++++++++++++++++ odb/semantics/relational/primary-key.cxx | 1 + odb/semantics/relational/primary-key.hxx | 8 +- odb/semantics/relational/table.cxx | 4 +- odb/semantics/relational/table.hxx | 4 +- 21 files changed, 479 insertions(+), 137 deletions(-) create mode 100644 odb/semantics/relational/elements.txx create mode 100644 odb/semantics/relational/name.cxx create mode 100644 odb/semantics/relational/name.hxx (limited to 'odb/semantics') diff --git a/odb/semantics/namespace.cxx b/odb/semantics/namespace.cxx index 25c1de0..ffba0e8 100644 --- a/odb/semantics/namespace.cxx +++ b/odb/semantics/namespace.cxx @@ -10,12 +10,13 @@ namespace semantics { namespace_:: namespace_ (path const& file, size_t line, size_t column, tree tn) - : node (file, line, column, tn) + : node (file, line, column, tn), original_ (0) { } namespace_:: namespace_ () + : original_ (0) { } diff --git a/odb/semantics/namespace.hxx b/odb/semantics/namespace.hxx index 7a886c5..96db4a7 100644 --- a/odb/semantics/namespace.hxx +++ b/odb/semantics/namespace.hxx @@ -13,6 +13,25 @@ namespace semantics class namespace_: public scope { public: + bool + extension () const + { + return original_ != 0; + } + + namespace_& + original () + { + return *original_; + } + + void + original (namespace_& ns) + { + original_ = &ns; + } + + public: namespace_ (path const&, size_t line, size_t column, tree); // Resolve conflict between scope::scope and nameable::scope. @@ -21,6 +40,9 @@ namespace semantics protected: namespace_ (); + + private: + namespace_* original_; }; } diff --git a/odb/semantics/relational/column.cxx b/odb/semantics/relational/column.cxx index 99df5d9..c3182eb 100644 --- a/odb/semantics/relational/column.cxx +++ b/odb/semantics/relational/column.cxx @@ -25,7 +25,7 @@ namespace semantics // { type_info ti (typeid (column)); - ti.add_base (typeid (nameable)); + ti.add_base (typeid (unameable)); insert (ti); } } diff --git a/odb/semantics/relational/column.hxx b/odb/semantics/relational/column.hxx index a1024cf..56487c6 100644 --- a/odb/semantics/relational/column.hxx +++ b/odb/semantics/relational/column.hxx @@ -15,13 +15,13 @@ namespace semantics { class contains; - class column: public nameable + class column: public unameable { typedef std::vector contained_list; public: column (string const& id, string const& type, bool null) - : nameable (id), type_ (type), null_ (null) + : unameable (id), type_ (type), null_ (null) { } @@ -96,7 +96,7 @@ namespace semantics contained_.push_back (&e); } - using nameable::add_edge_right; + using unameable::add_edge_right; virtual string kind () const diff --git a/odb/semantics/relational/elements.cxx b/odb/semantics/relational/elements.cxx index 6ab977a..42755c8 100644 --- a/odb/semantics/relational/elements.cxx +++ b/odb/semantics/relational/elements.cxx @@ -6,87 +6,27 @@ #include #include -#include -#include namespace semantics { namespace relational { - // scope + // duplicate_name // - - scope::names_iterator scope:: - find (string const& name) - { - names_map::iterator i (names_map_.find (name)); - - if (i == names_map_.end ()) - return names_.end (); - else - return i->second; - } - - scope::names_const_iterator scope:: - find (string const& name) const + template <> + duplicate_name:: + duplicate_name (uscope& s, unameable& o, unameable& d) + : scope (s), orig (o), dup (d), + orig_name (o.name ()), dup_name (d.name ()) { - names_map::const_iterator i (names_map_.find (name)); - - if (i == names_map_.end ()) - return names_.end (); - else - return names_const_iterator (i->second); } - scope::names_iterator scope:: - find (names const& e) + template <> + duplicate_name:: + duplicate_name (qscope& s, qnameable& o, qnameable& d) + : scope (s), orig (o), dup (d), + orig_name (o.name ().string ()), dup_name (d.name ().string ()) { - names_iterator_map::iterator i (iterator_map_.find (&e)); - return i != iterator_map_.end () ? i->second : names_.end (); - } - - scope::names_const_iterator scope:: - find (names const& e) const - { - names_iterator_map::const_iterator i (iterator_map_.find (&e)); - return i != iterator_map_.end () ? i->second : names_.end (); - } - - void scope:: - add_edge_left (names& e) - { - nameable& n (e.nameable ()); - string const& name (e.name ()); - - names_map::iterator i (names_map_.find (name)); - - if (i == names_map_.end ()) - { - names_list::iterator i; - - // We want the order to be columns first, then the primary key, - // and then the foreign keys. - // - if (n.is_a ()) - i = names_.insert (first_key_, &e); - else - { - if (n.is_a ()) - first_key_ = i = names_.insert (first_key_, &e); - else - { - i = names_.insert (names_.end (), &e); - - if (first_key_ == names_.end ()) - first_key_ = i; - } - } - - names_map_[name] = i; - iterator_map_[&e] = i; - } - else - throw duplicate_name (*this, (*i->second)->nameable (), n); } // type info @@ -110,7 +50,13 @@ namespace semantics // names // { - type_info ti (typeid (names)); + type_info ti (typeid (unames)); + ti.add_base (typeid (edge)); + insert (ti); + } + + { + type_info ti (typeid (qnames)); ti.add_base (typeid (edge)); insert (ti); } @@ -118,7 +64,13 @@ namespace semantics // nameable // { - type_info ti (typeid (nameable)); + type_info ti (typeid (unameable)); + ti.add_base (typeid (node)); + insert (ti); + } + + { + type_info ti (typeid (qnameable)); ti.add_base (typeid (node)); insert (ti); } @@ -126,7 +78,13 @@ namespace semantics // scope // { - type_info ti (typeid (scope)); + type_info ti (typeid (uscope)); + ti.add_base (typeid (node)); + insert (ti); + } + + { + type_info ti (typeid (qscope)); ti.add_base (typeid (node)); insert (ti); } diff --git a/odb/semantics/relational/elements.hxx b/odb/semantics/relational/elements.hxx index d07902d..d8711b3 100644 --- a/odb/semantics/relational/elements.hxx +++ b/odb/semantics/relational/elements.hxx @@ -16,6 +16,8 @@ #include #include +#include + namespace semantics { namespace relational @@ -84,18 +86,23 @@ namespace semantics // // + template class scope; + + template class nameable; // // + template class names: public edge { public: - typedef relational::scope scope_type; - typedef relational::nameable nameable_type; + typedef N name_type; + typedef relational::scope scope_type; + typedef relational::nameable nameable_type; - string const& + name_type const& name () const { return name_; @@ -114,7 +121,7 @@ namespace semantics } public: - names (string const& name): name_ (name) {} + names (name_type const& name): name_ (name) {} void set_left_node (scope_type& n) @@ -129,19 +136,25 @@ namespace semantics } protected: - string name_; + name_type name_; scope_type* scope_; nameable_type* nameable_; }; + typedef names unames; + typedef names qnames; + // // + template class nameable: public virtual node { public: - typedef relational::scope scope_type; + typedef N name_type; + typedef relational::names names_type; + typedef relational::scope scope_type; - string const& + name_type const& name () const { return named_->name (); @@ -153,7 +166,7 @@ namespace semantics return named ().scope (); } - names& + names_type& named () const { return *named_; @@ -170,7 +183,7 @@ namespace semantics nameable (string const& id): id_ (id), named_ (0) {} void - add_edge_right (names& e) + add_edge_right (names_type& e) { assert (named_ == 0); named_ = &e; @@ -180,38 +193,48 @@ namespace semantics private: string id_; - names* named_; + names_type* named_; }; + typedef nameable unameable; + typedef nameable qnameable; + // // struct duplicate_name { - typedef relational::scope scope_type; - typedef relational::nameable nameable_type; + template + duplicate_name (relational::scope&, + relational::nameable& orig, + relational::nameable& dup); - duplicate_name (scope_type& s, nameable_type& n, nameable_type& d) - : scope (s), nameable (n), duplicate (d) - { - } + node& scope; + node& orig; + node& dup; - scope_type& scope; - nameable_type& nameable; - nameable_type& duplicate; + string orig_name; + string dup_name; }; + template class scope: public virtual node { protected: - typedef std::list names_list; - typedef std::map names_map; - typedef std::map names_iterator_map; + typedef N name_type; + typedef relational::names names_type; + typedef relational::nameable nameable_type; + + typedef std::list names_list; + typedef std::map names_map; + typedef + std::map + names_iterator_map; public: - typedef pointer_iterator names_iterator; + typedef pointer_iterator names_iterator; typedef - pointer_iterator + pointer_iterator names_const_iterator; public: @@ -244,16 +267,16 @@ namespace semantics // Find. // names_iterator - find (string const& name); + find (name_type const&); names_const_iterator - find (string const& name) const; + find (name_type const&) const; names_iterator - find (names const&); + find (names_type const&); names_const_iterator - find (names const&) const; + find (names_type const&) const; public: scope () @@ -262,16 +285,21 @@ namespace semantics } void - add_edge_left (names&); + add_edge_left (names_type&); private: names_list names_; names_map names_map_; names_iterator_map iterator_map_; - names_list::iterator first_key_; + typename names_list::iterator first_key_; }; + + typedef scope uscope; + typedef scope qscope; } } +#include + #endif // ODB_SEMANTICS_RELATIONAL_ELEMENTS_HXX diff --git a/odb/semantics/relational/elements.txx b/odb/semantics/relational/elements.txx new file mode 100644 index 0000000..f3d15c2 --- /dev/null +++ b/odb/semantics/relational/elements.txx @@ -0,0 +1,94 @@ +// file : odb/semantics/relational/elements.txx +// author : Boris Kolpackov +// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +// license : GNU GPL v3; see accompanying LICENSE file + +namespace semantics +{ + namespace relational + { + // scope + // + + template + typename scope::names_iterator scope:: + find (name_type const& name) + { + typename names_map::iterator i (names_map_.find (name)); + + if (i == names_map_.end ()) + return names_.end (); + else + return i->second; + } + + template + typename scope::names_const_iterator scope:: + find (name_type const& name) const + { + typename names_map::const_iterator i (names_map_.find (name)); + + if (i == names_map_.end ()) + return names_.end (); + else + return names_const_iterator (i->second); + } + + template + typename scope::names_iterator scope:: + find (names_type const& e) + { + typename names_iterator_map::iterator i (iterator_map_.find (&e)); + return i != iterator_map_.end () ? i->second : names_.end (); + } + + template + typename scope::names_const_iterator scope:: + find (names_type const& e) const + { + typename names_iterator_map::const_iterator i (iterator_map_.find (&e)); + return i != iterator_map_.end () ? i->second : names_.end (); + } + + class column; + class primary_key; + + template + void scope:: + add_edge_left (names_type& e) + { + nameable_type& n (e.nameable ()); + name_type const& name (e.name ()); + + typename names_map::iterator i (names_map_.find (name)); + + if (i == names_map_.end ()) + { + typename names_list::iterator i; + + // We want the order to be columns first, then the primary key, + // and then the foreign keys. + // + if (n.is_a ()) + i = names_.insert (first_key_, &e); + else + { + if (n.is_a ()) + first_key_ = i = names_.insert (first_key_, &e); + else + { + i = names_.insert (names_.end (), &e); + + if (first_key_ == names_.end ()) + first_key_ = i; + } + } + + names_map_[name] = i; + iterator_map_[&e] = i; + } + else + throw duplicate_name (*this, (*i->second)->nameable (), n); + } + } +} diff --git a/odb/semantics/relational/foreign-key.cxx b/odb/semantics/relational/foreign-key.cxx index eae9c5f..610466a 100644 --- a/odb/semantics/relational/foreign-key.cxx +++ b/odb/semantics/relational/foreign-key.cxx @@ -25,6 +25,7 @@ namespace semantics // { type_info ti (typeid (foreign_key)); + ti.add_base (typeid (unameable)); ti.add_base (typeid (key)); insert (ti); } diff --git a/odb/semantics/relational/foreign-key.hxx b/odb/semantics/relational/foreign-key.hxx index 4a0b543..c47c90a 100644 --- a/odb/semantics/relational/foreign-key.hxx +++ b/odb/semantics/relational/foreign-key.hxx @@ -13,7 +13,7 @@ namespace semantics { namespace relational { - class foreign_key: public key + class foreign_key: public unameable, public key { public: enum action @@ -23,10 +23,10 @@ namespace semantics }; foreign_key (string const& id, - string const& referenced_table, + qname const& referenced_table, bool deferred, action on_delete = no_action) - : key (id), + : unameable (id), referenced_table_ (referenced_table), deferred_ (deferred), on_delete_ (on_delete) @@ -34,7 +34,7 @@ namespace semantics } public: - string + qname const& referenced_table () const { return referenced_table_; @@ -76,7 +76,7 @@ namespace semantics } private: - string referenced_table_; + qname referenced_table_; columns referenced_columns_; bool deferred_; action on_delete_; diff --git a/odb/semantics/relational/index.cxx b/odb/semantics/relational/index.cxx index 376a312..407dbf8 100644 --- a/odb/semantics/relational/index.cxx +++ b/odb/semantics/relational/index.cxx @@ -25,6 +25,7 @@ namespace semantics // { type_info ti (typeid (index)); + ti.add_base (typeid (qnameable)); ti.add_base (typeid (key)); insert (ti); } diff --git a/odb/semantics/relational/index.hxx b/odb/semantics/relational/index.hxx index ee6b202..bb34742 100644 --- a/odb/semantics/relational/index.hxx +++ b/odb/semantics/relational/index.hxx @@ -7,6 +7,7 @@ #define ODB_SEMANTICS_RELATIONAL_INDEX_HXX #include +#include #include #include @@ -17,7 +18,7 @@ namespace semantics // Note that unlike other keys, indexes are defined in the model // scope, not table scope. // - class index: public key + class index: public qnameable, public key { public: relational::table& @@ -28,7 +29,7 @@ namespace semantics public: index (string const& id) - : key (id) + : qnameable (id) { } diff --git a/odb/semantics/relational/key.cxx b/odb/semantics/relational/key.cxx index 648fb26..8fb28ca 100644 --- a/odb/semantics/relational/key.cxx +++ b/odb/semantics/relational/key.cxx @@ -33,7 +33,7 @@ namespace semantics // { type_info ti (typeid (key)); - ti.add_base (typeid (nameable)); + ti.add_base (typeid (node)); insert (ti); } } diff --git a/odb/semantics/relational/key.hxx b/odb/semantics/relational/key.hxx index 7e7a847..f714876 100644 --- a/odb/semantics/relational/key.hxx +++ b/odb/semantics/relational/key.hxx @@ -7,13 +7,13 @@ #define ODB_SEMANTICS_RELATIONAL_KEY_HXX #include -#include namespace semantics { namespace relational { class key; + class column; class contains: public edge { @@ -51,7 +51,7 @@ namespace semantics column_type* column_; }; - class key: public nameable + class key: public virtual node { typedef std::vector contains_list; @@ -85,12 +85,6 @@ namespace semantics contains_.push_back (&e); } - protected: - key (string const& id) - : nameable (id) - { - } - private: contains_list contains_; }; diff --git a/odb/semantics/relational/model.cxx b/odb/semantics/relational/model.cxx index a0ac23f..d19c835 100644 --- a/odb/semantics/relational/model.cxx +++ b/odb/semantics/relational/model.cxx @@ -25,7 +25,7 @@ namespace semantics // { type_info ti (typeid (model)); - ti.add_base (typeid (scope)); + ti.add_base (typeid (qscope)); insert (ti); } } diff --git a/odb/semantics/relational/model.hxx b/odb/semantics/relational/model.hxx index 7d2f944..a761af1 100644 --- a/odb/semantics/relational/model.hxx +++ b/odb/semantics/relational/model.hxx @@ -12,7 +12,7 @@ namespace semantics { namespace relational { - class model: public graph, public scope + class model: public graph, public qscope { public: model () @@ -26,8 +26,8 @@ namespace semantics } public: - using scope::add_edge_left; - using scope::add_edge_right; + using qscope::add_edge_left; + using qscope::add_edge_right; private: model (model const&); diff --git a/odb/semantics/relational/name.cxx b/odb/semantics/relational/name.cxx new file mode 100644 index 0000000..3cfd763 --- /dev/null +++ b/odb/semantics/relational/name.cxx @@ -0,0 +1,95 @@ +// file : odb/semantics/relational/name.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +// license : GNU GPL v3; see accompanying LICENSE file + +#include +#include + +#include + +using namespace std; + +namespace semantics +{ + namespace relational + { + string qname:: + string () const + { + std::string r; + + bool f (true); + for (iterator i (begin ()); i < end (); ++i) + { + if (i->empty ()) + continue; + + if (f) + f = false; + else + r += '.'; + + r += *i; + } + + return r; + } + + ostream& + operator<< (ostream& os, qname const& n) + { + bool f (true); + for (qname::iterator i (n.begin ()); i < n.end (); ++i) + { + if (i->empty ()) + continue; + + if (f) + f = false; + else + os << '.'; + + os << *i; + } + + return os; + } + + istream& + operator>> (istream& is, qname& n) + { + n.clear (); + + string s; + is >> s; + + if (!is.fail ()) + { + string::size_type p (string::npos); + + for (size_t i (0); i < s.size (); ++i) + { + char c (s[i]); + + if (c == '.') + { + if (p == string::npos) + n.append (string (s, 0, i)); + else + n.append (string (s, p + 1, i - p - 1)); + + p = i; + } + } + + if (p == string::npos) + n.append (s); + else + n.append (string (s, p + 1, string::npos)); + } + + return is; + } + } +} diff --git a/odb/semantics/relational/name.hxx b/odb/semantics/relational/name.hxx new file mode 100644 index 0000000..ae06708 --- /dev/null +++ b/odb/semantics/relational/name.hxx @@ -0,0 +1,146 @@ +// file : odb/semantics/relational/name.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +// license : GNU GPL v3; see accompanying LICENSE file + +#ifndef ODB_SEMANTICS_RELATIONAL_NAME_HXX +#define ODB_SEMANTICS_RELATIONAL_NAME_HXX + +#include +#include +#include + +namespace semantics +{ + namespace relational + { + typedef std::string uname; + + class qname + { + public: + typedef relational::uname uname_type; + + qname () {} + + explicit + qname (uname_type const& n) {append (n);} + + template + qname (I begin, I end) + { + for (; begin != end; ++begin) + append (*begin); + } + + qname& + operator= (uname_type const& n) + { + components_.resize (1); + components_[0] = n; + return *this; + } + + void + append (uname_type const& n) {components_.push_back (n);} + + void + append (qname const& n) + { + components_.insert (components_.end (), + n.components_.begin (), + n.components_.end ()); + } + + void + clear () {components_.clear ();} + + // Append a string to the last component. + // + qname& + operator+= (std::string const& s) + { + if (empty ()) + append (s); + else + uname () += s; + + return *this; + } + + friend qname + operator+ (qname const& n, std::string const& s) + { + qname r (n); + + if (r.empty ()) + r.append (s); + else + r.uname () += s; + + return r; + } + + void + swap (qname& n) {components_.swap (n.components_);} + + public: + bool + empty () const {return components_.empty ();} + + bool + qualified () const {return components_.size () > 1;} + + bool + fully_qualified () const + { + return qualified () && components_.front ().empty (); + } + + public: + typedef std::vector components; + typedef components::const_iterator iterator; + + iterator + begin () const {return components_.begin ();} + + iterator + end () const {return components_.end ();} + + uname_type& + uname () {return components_.back ();} + + uname_type const& + uname () const {return components_.back ();} + + qname + qualifier () const + { + return empty () + ? qname () + : qname (components_.begin (), components_.end () - 1); + } + + std::string + string () const; + + public: + friend bool + operator< (qname const& x, qname const& y) + { + return x.components_ < y.components_; + } + + private: + components components_; + }; + + std::ostream& + operator<< (std::ostream&, qname const&); + + std::istream& + operator>> (std::istream&, qname&); + } +} + +#endif // ODB_SEMANTICS_RELATIONAL_NAME_HXX diff --git a/odb/semantics/relational/primary-key.cxx b/odb/semantics/relational/primary-key.cxx index 367013e..5794f9a 100644 --- a/odb/semantics/relational/primary-key.cxx +++ b/odb/semantics/relational/primary-key.cxx @@ -25,6 +25,7 @@ namespace semantics // { type_info ti (typeid (primary_key)); + ti.add_base (typeid (unameable)); ti.add_base (typeid (key)); insert (ti); } diff --git a/odb/semantics/relational/primary-key.hxx b/odb/semantics/relational/primary-key.hxx index a35e8f5..7402b8a 100644 --- a/odb/semantics/relational/primary-key.hxx +++ b/odb/semantics/relational/primary-key.hxx @@ -13,7 +13,7 @@ namespace semantics { namespace relational { - class primary_key: public key + class primary_key: public unameable, public key { public: bool @@ -23,10 +23,10 @@ namespace semantics } public: - // Primary key has the implicit empty id. - // primary_key (bool auto_) - : key (""), auto__ (auto_) + // Primary key has the implicit empty id. + // + : unameable (""), auto__ (auto_) { } diff --git a/odb/semantics/relational/table.cxx b/odb/semantics/relational/table.cxx index a9290c6..5b3ec68 100644 --- a/odb/semantics/relational/table.cxx +++ b/odb/semantics/relational/table.cxx @@ -25,8 +25,8 @@ namespace semantics // { type_info ti (typeid (table)); - ti.add_base (typeid (nameable)); - ti.add_base (typeid (scope)); + ti.add_base (typeid (qnameable)); + ti.add_base (typeid (uscope)); insert (ti); } diff --git a/odb/semantics/relational/table.hxx b/odb/semantics/relational/table.hxx index d2f8649..cd031b8 100644 --- a/odb/semantics/relational/table.hxx +++ b/odb/semantics/relational/table.hxx @@ -12,11 +12,11 @@ namespace semantics { namespace relational { - class table: public nameable, public scope + class table: public qnameable, public uscope { protected: table (string const& id) - : nameable (id) + : qnameable (id) { } }; -- cgit v1.1