From 823026b58211a4166de06ac243d978dcb9930271 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Mon, 22 Jan 2024 15:58:08 +0300 Subject: Turn odb repository into muti-package repository Also remove the autoconf/make-based build system. --- odb/relational/schema.hxx | 1606 --------------------------------------------- 1 file changed, 1606 deletions(-) delete mode 100644 odb/relational/schema.hxx (limited to 'odb/relational/schema.hxx') diff --git a/odb/relational/schema.hxx b/odb/relational/schema.hxx deleted file mode 100644 index cd975b7..0000000 --- a/odb/relational/schema.hxx +++ /dev/null @@ -1,1606 +0,0 @@ -// file : odb/relational/schema.hxx -// license : GNU GPL v3; see accompanying LICENSE file - -#ifndef ODB_RELATIONAL_SCHEMA_HXX -#define ODB_RELATIONAL_SCHEMA_HXX - -#include -#include -#include - -#include -#include -#include - -namespace relational -{ - namespace schema - { - typedef std::set table_set; - - struct common: virtual context - { - typedef ::emitter emitter_type; - - common (emitter_type& e, ostream& os, schema_format f) - : e_ (e), os_ (os), format_ (f) {} - - void - pre_statement () - { - e_.pre (); - diverge (os_); - } - - void - post_statement () - { - restore (); - e_.post (); - } - - emitter_type& - emitter () const - { - return e_; - } - - ostream& - stream () const - { - return os_; - } - - public: - // Find an entity corresponding to the drop node in alter_table. - // - template - T& - find (D& d) - { - using sema_rel::model; - using sema_rel::changeset; - using sema_rel::table; - using sema_rel::alter_table; - - alter_table& at (dynamic_cast (d.scope ())); - changeset& cs (dynamic_cast (at.scope ())); - model& bm (cs.base_model ()); - table* bt (bm.find (at.name ())); - assert (bt != 0); - T* b (bt->find (d.name ())); - assert (b != 0); - return *b; - } - - protected: - emitter_type& e_; - ostream& os_; - schema_format format_; - }; - - // - // Drop. - // - - // Only used in migration. - // - struct drop_column: trav_rel::drop_column, common - { - typedef drop_column base; - - drop_column (common const& c, bool* first = 0) - : common (c), - first_ (first != 0 ? *first : first_data_), - first_data_ (true) - { - } - - drop_column (drop_column const& c) - : root_context (), // @@ -Wextra - context (), - common (c), - first_ (&c.first_ != &c.first_data_ ? c.first_ : first_data_), - first_data_ (c.first_data_) - { - } - - virtual void - drop_header () - { - // By default ADD COLUMN though some databases use just ADD. - // - os << "DROP COLUMN "; - } - - virtual void - traverse (sema_rel::drop_column& dc) - { - if (first_) - first_ = false; - else - os << ","; - - os << endl - << " "; - drop_header (); - os << quote_id (dc.name ()); - } - - protected: - bool& first_; - bool first_data_; - }; - - // Normally only used in migration but some databases use it as a - // base to also drop foreign keys in schema. - // - struct drop_foreign_key: trav_rel::foreign_key, - trav_rel::drop_foreign_key, - trav_rel::add_foreign_key, // Override. - common - { - typedef drop_foreign_key base; - - // Schema constructor. - // - drop_foreign_key (common const& c, table_set& dropped, bool* first = 0) - : common (c), - dropped_ (&dropped), - first_ (first != 0 ? *first : first_data_), - first_data_ (true) - { - } - - // Migration constructor. - // - drop_foreign_key (common const& c, bool* first = 0) - : common (c), - dropped_ (0), - first_ (first != 0 ? *first : first_data_), - first_data_ (true) - { - } - - drop_foreign_key (drop_foreign_key const& c) - : root_context (), // @@ -Wextra - context (), - common (c), - dropped_ (c.dropped_), - first_ (&c.first_ != &c.first_data_ ? c.first_ : first_data_), - first_data_ (c.first_data_) - { - } - - virtual void - drop_header () - { - os << "DROP CONSTRAINT "; - } - - virtual void - traverse (sema_rel::foreign_key& fk) - { - // If the table which we reference is droped before us, then - // we need to drop the constraint first. Similarly, if the - // referenced table is not part if this model, then assume - // it is dropped before us. In migration we always do this - // first. - // - sema_rel::table& t (dynamic_cast (fk.scope ())); - - if (dropped_ != 0) - { - sema_rel::qname const& rt (fk.referenced_table ()); - sema_rel::model& m (dynamic_cast (t.scope ())); - - if (dropped_->find (rt) == dropped_->end () && - m.find (rt) != m.names_end ()) - return; - } - - drop (t, fk); - } - - virtual void - drop (sema_rel::table& t, sema_rel::foreign_key& fk) - { - // When generating schema we would need to check if the key exists. - // So this implementation will need to be customize on the per- - // database level. - // - pre_statement (); - - os << "ALTER TABLE " << quote_id (t.name ()) << endl - << " "; - drop_header (); - os << quote_id (fk.name ()) << endl; - - post_statement (); - } - - virtual void - traverse (sema_rel::drop_foreign_key& dfk) - { - if (first_) - first_ = false; - else - os << ","; - - os << endl; - drop (dfk); - } - - virtual void - drop (sema_rel::drop_foreign_key& dfk) - { - os << " "; - drop_header (); - os << quote_id (dfk.name ()); - } - - protected: - table_set* dropped_; - bool& first_; - bool first_data_; - }; - - // Currently only used in migration. - // - struct drop_index: trav_rel::drop_index, common - { - typedef drop_index base; - - enum index_type {unique, non_unique, all}; - - drop_index (common const& c, index_type t = all) - : common (c), type_ (t) {} - - virtual void - traverse (sema_rel::drop_index& di) - { - // Find the index we are dropping in the base model. - // - traverse (find (di)); - } - - virtual void - traverse (sema_rel::index& in) - { - if (type_ == unique && - in.type ().find ("UNIQUE") == string::npos && - in.type ().find ("unique") == string::npos) - return; - - if (type_ == non_unique && ( - in.type ().find ("UNIQUE") != string::npos || - in.type ().find ("unique") != string::npos)) - return; - - pre_statement (); - drop (in); - post_statement (); - } - - virtual string - name (sema_rel::index& in) - { - return quote_id (in.name ()); - } - - virtual void - drop (sema_rel::index& in) - { - os << "DROP INDEX " << name (in) << endl; - } - - protected: - index_type type_; - }; - - struct drop_table: trav_rel::table, - trav_rel::drop_table, - trav_rel::add_table, // Override. - trav_rel::alter_table, // Override. - common - { - typedef drop_table base; - - drop_table (emitter_type& e, ostream& os, schema_format f) - : common (e, os, f) {} - - virtual void - drop (sema_rel::table& t, bool migration) - { - pre_statement (); - os << "DROP TABLE " << (migration ? "" : "IF EXISTS ") << - quote_id (t.name ()) << endl; - post_statement (); - } - - virtual void - delete_ (sema_rel::qname const& rtable, - sema_rel::qname const& dtable, - sema_rel::primary_key& rkey, - sema_rel::primary_key& dkey) - { - pre_statement (); - - // This might not be the most efficient way for every database. - // - os << "DELETE FROM " << quote_id (rtable) << endl - << " WHERE EXISTS (SELECT 1 FROM " << quote_id (dtable) << endl - << " WHERE "; - - for (size_t i (0); i != rkey.contains_size (); ++i) - { - if (i != 0) - os << endl - << " AND "; - - os << quote_id (rtable) << "." << - quote_id (rkey.contains_at (i).column ().name ()) << " = " << - quote_id (dtable) << "." << - quote_id (dkey.contains_at (i).column ().name ()); - } - - os << ")" << endl; - - post_statement (); - } - - virtual void - traverse (sema_rel::table& t, bool migration) - { - // By default drop foreign keys referencing tables that would - // have already been dropped on the first pass. - // - if (pass_ == 1) - { - // Drop constraints. In migration this is always done on pass 1. - // - if (migration) - { - instance dfk (*this); - trav_rel::unames n (*dfk); - names (t, n); - } - else - { - dropped_.insert (t.name ()); // Add it before to cover self-refs. - - instance dfk (*this, dropped_); - trav_rel::unames n (*dfk); - names (t, n); - } - } - else - { - if (migration && t.extra ()["kind"] == "polymorphic derived object") - { - // If we are dropping a polymorphic derived object, then we - // also have to clean the base tables. Note that this won't - // trigger cascade deletion since we have dropped all the - // keys on pass 1. But we still need to do this in the base - // to root order in order not to trigger other cascades. - // - using sema_rel::model; - using sema_rel::table; - using sema_rel::primary_key; - using sema_rel::foreign_key; - - model& m (dynamic_cast (t.scope ())); - - table* p (&t); - do - { - // The polymorphic link is the first primary key. - // - for (table::names_iterator i (p->names_begin ()); - i != p->names_end (); ++i) - { - if (foreign_key* fk = dynamic_cast ( - &i->nameable ())) - { - p = m.find
(fk->referenced_table ()); - assert (p != 0); // Base table should be there. - break; - } - } - - primary_key& rkey (*p->find ("")); - primary_key& dkey (*t.find ("")); - assert (rkey.contains_size () == dkey.contains_size ()); - delete_ (p->name (), t.name (), rkey, dkey); - } - while (p->extra ()["kind"] != "polymorphic root object"); - } - - drop (t, migration); - } - } - - virtual void - traverse (sema_rel::table& t) - { - traverse (t, false); - } - - virtual void - traverse (sema_rel::drop_table& dt) - { - using sema_rel::model; - using sema_rel::changeset; - using sema_rel::table; - - // Find the table we are dropping in the base model. - // - changeset& cs (dynamic_cast (dt.scope ())); - model& bm (cs.base_model ()); - table* t (bm.find
(dt.name ())); - assert (t != 0); - traverse (*t, true); - } - - using add_table::traverse; // Unhide. - using alter_table::traverse; // Unhide. - - using table::names; - - void - pass (unsigned short p) - { - pass_ = p; - } - - protected: - unsigned short pass_; - table_set dropped_; - }; - - struct drop_model: trav_rel::model, common - { - typedef drop_model base; - - drop_model (emitter_type& e, ostream& os, schema_format f) - : common (e, os, f) - { - } - - virtual void - traverse (sema_rel::model& m) - { - // Traverse named entities in the reverse order. This way we - // drop them in the order opposite to creating. - // - for (sema_rel::model::names_iterator begin (m.names_begin ()), - end (m.names_end ()); begin != end;) - dispatch (*--end); - } - - void - pass (unsigned short p) - { - pass_ = p; - } - - protected: - unsigned short pass_; - }; - - // - // Create. - // - - struct create_column: trav_rel::column, - trav_rel::add_column, - trav_rel::alter_column, // Override. - common - { - typedef create_column base; - - create_column (common const& c, - bool override_null = true, - bool* first = 0) - : common (c), - override_null_ (override_null), - first_ (first != 0 ? *first : first_data_), - first_data_ (true) - { - } - - create_column (create_column const& c) - : root_context (), // @@ -Wextra - context (), - common (c), - override_null_ (c.override_null_), - first_ (&c.first_ != &c.first_data_ ? c.first_ : first_data_), - first_data_ (c.first_data_) - { - } - - virtual void - traverse (sema_rel::column& c) - { - if (first_) - first_ = false; - else - os << ","; - - os << endl - << " "; - create (c); - } - - virtual void - add_header () - { - // By default ADD COLUMN though some databases use just ADD. - // - os << "ADD COLUMN "; - } - - virtual void - traverse (sema_rel::add_column& ac) - { - if (first_) - first_ = false; - else - os << ","; - - os << endl - << " "; - add_header (); - create (ac); - } - - virtual void - create (sema_rel::column& c) - { - using sema_rel::column; - - // See if this column is (part of) a primary key. - // - sema_rel::primary_key* pk (0); - - for (column::contained_iterator i (c.contained_begin ()); - i != c.contained_end (); - ++i) - { - if ((pk = dynamic_cast (&i->key ()))) - break; - } - - os << quote_id (c.name ()) << " "; - - type (c, pk != 0 && pk->auto_ ()); - constraints (c, pk); - - if (!c.options ().empty ()) - os << " " << c.options (); - } - - virtual void - constraints (sema_rel::column& c, sema_rel::primary_key* pk) - { - null (c); - - if (!c.default_ ().empty ()) - os << " DEFAULT " << c.default_ (); - - // If this is a single-column primary key, generate it inline. - // - if (pk != 0 && pk->contains_size () == 1) - primary_key (); - - if (pk != 0 && pk->auto_ ()) - auto_ (*pk); - } - - virtual void - type (sema_rel::column& c, bool /*auto*/) - { - os << c.type (); - } - - virtual void - null (sema_rel::column& c) - { - bool n (c.null ()); - - // If we are adding a new column that doesn't allow NULL nor has - // a default value, add it as NULL. Later, after migration, we - // will convert it to NOT NULL. - // - if (override_null_ && c.is_a () && - !n && c.default_ ().empty ()) - n = true; - - // Specify both cases explicitly for better readability, - // especially in ALTER COLUMN clauses. - // - os << (n ? " NULL" : " NOT NULL"); - } - - virtual void - primary_key () - { - os << " PRIMARY KEY"; - } - - virtual void - auto_ (sema_rel::primary_key&) - { - } - - protected: - bool override_null_; // Override NOT NULL in add_column. - bool& first_; - bool first_data_; - bool add_; - }; - - struct create_primary_key: trav_rel::primary_key, common - { - typedef create_primary_key base; - - create_primary_key (common const& c): common (c) {} - - virtual void - traverse (sema_rel::primary_key& pk) - { - // Single-column primary keys are generated inline in the - // column declaration. - // - if (pk.contains_size () == 1) - return; - - // We will always follow a column. - // - os << "," << endl; - - create (pk); - } - - virtual void - create (sema_rel::primary_key& pk) - { - using sema_rel::primary_key; - - // By default we create unnamed primary key constraint. - // - - os << " PRIMARY KEY ("; - - for (primary_key::contains_iterator i (pk.contains_begin ()); - i != pk.contains_end (); - ++i) - { - if (i != pk.contains_begin ()) - os << "," << endl - << " "; - - os << quote_id (i->column ().name ()); - } - - os << ")"; - } - }; - - struct create_foreign_key: trav_rel::foreign_key, - trav_rel::add_foreign_key, - common - { - typedef create_foreign_key base; - - // Schema constructor, pass 1. - // - create_foreign_key (common const& c, table_set& created, bool* first = 0) - : common (c), - created_ (&created), - first_ (first != 0 ? *first : first_data_), - first_data_ (true) - { - } - - // Schema constructor, pass 2 and migration constructor. - // - create_foreign_key (common const& c, bool* first = 0) - : common (c), - created_ (0), - first_ (first != 0 ? *first : first_data_), - first_data_ (true) - { - } - - create_foreign_key (create_foreign_key const& c) - : root_context (), // @@ -Wextra - context (), - common (c), - created_ (c.created_), - first_ (&c.first_ != &c.first_data_ ? c.first_ : first_data_), - first_data_ (c.first_data_) - { - } - - virtual void - traverse (sema_rel::foreign_key& fk) - { - if (created_ != 0) - { - // Pass 1. - // - // If the referenced table has already been defined, do the - // foreign key definition in the table definition. Otherwise - // postpone it until pass 2 where we do it via ALTER TABLE. - // - if (created_->find (fk.referenced_table ()) != created_->end ()) - { - traverse_create (fk); - fk.set (db.string () + "-fk-defined", true); // Mark it as defined. - } - } - else - { - // Pass 2. - // - if (!fk.count (db.string () + "-fk-defined")) - traverse_add (fk); - } - } - - virtual void - traverse_create (sema_rel::foreign_key& fk) - { - if (first_) - first_ = false; - else - os << ","; - - os << endl - << " CONSTRAINT "; - create (fk); - } - - virtual void - traverse_add (sema_rel::foreign_key& fk) - { - if (first_) - first_ = false; - else - os << ","; - - os << endl; - add (fk); - } - - virtual void - traverse (sema_rel::add_foreign_key& afk) - { - traverse_add (afk); - } - - virtual void - add_header () - { - os << "ADD CONSTRAINT "; - } - - virtual void - add (sema_rel::foreign_key& fk) - { - os << " "; - add_header (); - create (fk); - } - - virtual void - create (sema_rel::foreign_key& fk) - { - using sema_rel::foreign_key; - - os << name (fk) << endl - << " FOREIGN KEY ("; - - for (foreign_key::contains_iterator i (fk.contains_begin ()); - i != fk.contains_end (); - ++i) - { - if (i != fk.contains_begin ()) - os << "," << endl - << " "; - - os << quote_id (i->column ().name ()); - } - - string tn (table_name (fk)); - string tn_pad (tn.size (), ' '); - - os << ")" << endl - << " REFERENCES " << tn << " ("; - - foreign_key::columns const& refs (fk.referenced_columns ()); - for (foreign_key::columns::const_iterator i (refs.begin ()); - i != refs.end (); - ++i) - { - if (i != refs.begin ()) - os << "," << endl - << " " << tn_pad; - - os << quote_id (*i); - } - - os << ")"; - - if (fk.on_delete () != foreign_key::no_action) - on_delete (fk.on_delete ()); - - if (!fk.not_deferrable ()) - deferrable (fk.deferrable ()); - } - - virtual string - name (sema_rel::foreign_key& fk) - { - return quote_id (fk.name ()); - } - - virtual string - table_name (sema_rel::foreign_key& fk) - { - return quote_id (fk.referenced_table ()); - } - - virtual void - on_delete (sema_rel::foreign_key::action_type a) - { - using sema_rel::foreign_key; - - switch (a) - { - case foreign_key::no_action: - break; - case foreign_key::cascade: - { - os << endl - << " ON DELETE CASCADE"; - break; - } - case foreign_key::set_null: - { - os << endl - << " ON DELETE SET NULL"; - break; - } - } - } - - virtual void - deferrable (sema_rel::deferrable d) - { - os << endl - << " DEFERRABLE INITIALLY " << d; - } - - protected: - table_set* created_; - bool& first_; - bool first_data_; - }; - - struct create_index: trav_rel::index, common - { - typedef create_index base; - - enum index_type {unique, non_unique, all}; - - create_index (common const& c, index_type t = all) - : common (c), type_ (t) {} - - virtual void - traverse (sema_rel::index& in) - { - if (type_ == unique && - in.type ().find ("UNIQUE") == string::npos && - in.type ().find ("unique") == string::npos) - return; - - if (type_ == non_unique && ( - in.type ().find ("UNIQUE") != string::npos || - in.type ().find ("unique") != string::npos)) - return; - - pre_statement (); - create (in); - post_statement (); - } - - virtual string - name (sema_rel::index& in) - { - return quote_id (in.name ()); - } - - virtual string - table_name (sema_rel::index& in) - { - return quote_id (static_cast (in.scope ()).name ()); - } - - virtual void - columns (sema_rel::index& in) - { - using sema_rel::index; - - for (index::contains_iterator i (in.contains_begin ()); - i != in.contains_end (); - ++i) - { - if (in.contains_size () > 1) - { - if (i != in.contains_begin ()) - os << ","; - - os << endl - << " "; - } - - os << quote_id (i->column ().name ()); - - if (!i->options ().empty ()) - os << ' ' << i->options (); - } - } - - virtual void - create (sema_rel::index& in) - { - // Default implementation that ignores the method. - // - os << "CREATE "; - - if (!in.type ().empty ()) - os << in.type () << ' '; - - os << "INDEX " << name (in) << endl - << " ON " << table_name (in) << " ("; - - columns (in); - - os << ")" << endl; - - if (!in.options ().empty ()) - os << ' ' << in.options () << endl; - } - - protected: - index_type type_; - }; - - struct create_table: trav_rel::table, - trav_rel::alter_table, // Override. - common - { - typedef create_table base; - - using trav_rel::table::names; - - create_table (emitter_type& e, ostream& os, schema_format f) - : common (e, os, f) {} - - virtual void - create_pre (sema_rel::qname const& table) - { - os << "CREATE TABLE " << quote_id (table) << " ("; - } - - virtual void - create_post (sema_rel::table& t) - { - os << ")" << endl; - - if (!t.options ().empty ()) - os << " " << t.options () << endl; - } - - virtual void - create (sema_rel::table& t) - { - pre_statement (); - create_pre (t.name ()); - - instance c (*this); - instance pk (*this); - - // We will always follow a column, so set first to false. - // - bool f (false); // (Im)perfect forwarding. - bool* pf (&f); // (Im)perfect forwarding. - instance fk (*this, created_, pf); - - trav_rel::unames n; - n >> c; - n >> pk; - n >> fk; - - names (t, n); - - create_post (t); - post_statement (); - - // Create indexes. - // - { - instance in (*this); - trav_rel::unames n (*in); - names (t, n); - } - } - - // See if there are any undefined foreign keys that we need to - // add with ALTER TABLE. - // - bool - check_undefined_fk (sema_rel::table& t) - { - for (sema_rel::table::names_iterator i (t.names_begin ()); - i != t.names_end (); ++i) - { - if (i->nameable ().is_a () && - !i->nameable ().count (db.string () + "-fk-defined")) - return true; - } - return false; - } - - virtual void - traverse (sema_rel::table& t) - { - // By default add foreign keys referencing tables that haven't - // yet been defined on the second pass. - // - if (pass_ == 1) - { - // In migration we always add foreign keys on pass 2. - // - if (!t.is_a ()) - created_.insert (t.name ()); // Add it before to cover self-refs. - - create (t); - } - else - { - // Add undefined foreign keys. - // - if (check_undefined_fk (t)) - { - pre_statement (); - os << "ALTER TABLE " << quote_id (t.name ()); - - instance cfk (*this); - trav_rel::unames n (*cfk); - names (t, n); - os << endl; - - post_statement (); - } - } - } - - void - pass (unsigned short p) - { - pass_ = p; - } - - protected: - unsigned short pass_; - table_set created_; - }; - - struct create_model: trav_rel::model, common - { - typedef create_model base; - - create_model (emitter_type& e, ostream& os, schema_format f) - : common (e, os, f) {} - - void - pass (unsigned short p) - { - pass_ = p; - } - - protected: - unsigned short pass_; - }; - - // - // Alter. - // - - struct alter_column: trav_rel::alter_column, - trav_rel::add_column, - common - { - typedef alter_column base; - - alter_column (common const& c, bool pre, bool* first = 0) - : common (c), - pre_ (pre), - first_ (first != 0 ? *first : first_data_), - first_data_ (true), - fl_ (false), - def_ (c, fl_) - { - } - - alter_column (alter_column const& c) - : root_context (), // @@ -Wextra - context (), - common (c), - pre_ (c.pre_), - first_ (&c.first_ != &c.first_data_ ? c.first_ : first_data_), - first_data_ (c.first_data_), - fl_ (false), - def_ (c, fl_) - { - } - - virtual void - alter_header () - { - os << "ALTER COLUMN "; - } - - virtual void - alter (sema_rel::column& c) - { - // By default use the whole definition. - // - def_->create (c); - } - - virtual void - traverse (sema_rel::column& c) - { - // Relax (NULL) in pre and tighten (NOT NULL) in post. - // - if (pre_ != c.null ()) - return; - - if (first_) - first_ = false; - else - os << ","; - - os << endl - << " "; - alter_header (); - alter (c); - } - - virtual void - traverse (sema_rel::alter_column& ac) - { - assert (ac.null_altered ()); - traverse (static_cast (ac)); - } - - virtual void - traverse (sema_rel::add_column& ac) - { - // We initially add NOT NULL columns without default values as - // NULL. Now, after the migration, we convert them to NOT NULL. - // - if (!ac.null () && ac.default_ ().empty ()) - traverse (static_cast (ac)); - } - - protected: - bool pre_; - bool& first_; - bool first_data_; - bool fl_; // (Im)perfect forwarding. - instance def_; - }; - - struct alter_table_common: trav_rel::alter_table, common - { - alter_table_common (emitter_type& e, ostream& os, schema_format f) - : common (e, os, f) {} - - template - T* - check (sema_rel::alter_table& at) - { - for (sema_rel::alter_table::names_iterator i (at.names_begin ()); - i != at.names_end (); ++i) - { - if (T* x = dynamic_cast (&i->nameable ())) - return x; - } - return 0; - } - - sema_rel::column* - check_alter_column_null (sema_rel::alter_table& at, bool v) - { - for (sema_rel::alter_table::names_iterator i (at.names_begin ()); - i != at.names_end (); ++i) - { - using sema_rel::add_column; - using sema_rel::alter_column; - - if (alter_column* ac = dynamic_cast (&i->nameable ())) - { - if (ac->null_altered () && ac->null () == v) - return ac; - } - - // If we are testing for NOT NULL, also look for new columns that - // we initially add as NULL and later convert to NOT NULL. - // - if (!v) - { - if (add_column* ac = dynamic_cast (&i->nameable ())) - { - if (!ac->null () && ac->default_ ().empty ()) - return ac; - } - } - } - return 0; - } - - void - pass (unsigned short p) - { - pass_ = p; - } - - protected: - unsigned short pass_; - }; - - struct alter_table_pre: alter_table_common - { - typedef alter_table_pre base; - - alter_table_pre (emitter_type& e, ostream& os, schema_format f) - : alter_table_common (e, os, f) {} - - // Check if there will be any clauses in ALTER TABLE. - // - using alter_table_common::check; - - virtual bool - check (sema_rel::alter_table& at) - { - // If changing the below test, make sure to also update tests - // in database-specific code. - // - return - check (at) || - check (at) || - check_alter_column_null (at, true); - } - - virtual void - alter (sema_rel::alter_table& at) - { - // By default we generate all the alterations in a single ALTER TABLE - // statement. Quite a few databases don't support this. - // - pre_statement (); - os << "ALTER TABLE " << quote_id (at.name ()); - - bool f (true); // Shared first flag. - bool* pf (&f); // (Im)perfect forwarding. - bool tl (true); // (Im)perfect forwarding. - instance cc (*this, tl, pf); - instance ac (*this, tl, pf); - instance dfk (*this, pf); - trav_rel::unames n; - n >> cc; - n >> ac; - n >> dfk; - names (at, n); - os << endl; - - post_statement (); - } - - virtual void - traverse (sema_rel::alter_table& at) - { - if (pass_ == 1) - { - // Drop unique indexes. - // - { - drop_index::index_type it (drop_index::unique); - instance in (*this, it); - trav_rel::unames n (*in); - names (at, n); - } - - if (check (at)) - alter (at); - } - else - { - // Add non-unique indexes. - // - { - create_index::index_type it (create_index::non_unique); - instance in (*this, it); - trav_rel::unames n (*in); - names (at, n); - } - } - } - }; - - struct changeset_pre: trav_rel::changeset, common - { - typedef changeset_pre base; - - changeset_pre (emitter_type& e, ostream& os, schema_format f) - : common (e, os, f) {} - - void - pass (unsigned short p) - { - pass_ = p; - } - - protected: - unsigned short pass_; - }; - - struct alter_table_post: alter_table_common - { - typedef alter_table_post base; - - alter_table_post (emitter_type& e, ostream& os, schema_format f) - : alter_table_common (e, os, f) {} - - // Check if there will be any clauses in ALTER TABLE. - // - using alter_table_common::check; - - virtual bool - check (sema_rel::alter_table& at) - { - // If changing the below test, make sure to also update tests - // in database-specific code. - // - return - check (at) || - check (at) || - check_alter_column_null (at, false); - } - - virtual void - alter (sema_rel::alter_table& at) - { - // By default we generate all the alterations in a single ALTER TABLE - // statement. Quite a few databases don't support this. - // - pre_statement (); - os << "ALTER TABLE " << quote_id (at.name ()); - - bool f (true); // Shared first flag. - bool* pf (&f); // (Im)perfect forwarding. - bool fl (false); // (Im)perfect forwarding. - instance dc (*this, pf); - instance ac (*this, fl, pf); - instance fk (*this, pf); - - trav_rel::unames n; - n >> dc; - n >> ac; - n >> fk; - names (at, n); - os << endl; - - post_statement (); - } - - virtual void - traverse (sema_rel::alter_table& at) - { - if (pass_ == 1) - { - // Drop non-unique indexes. - // - { - drop_index::index_type it (drop_index::non_unique); - instance in (*this, it); - trav_rel::unames n (*in); - names (at, n); - } - } - else - { - if (check (at)) - alter (at); - - // Add unique indexes. - // - { - create_index::index_type it (create_index::unique); - instance in (*this, it); - trav_rel::unames n (*in); - names (at, n); - } - } - } - }; - - struct changeset_post: trav_rel::changeset, common - { - typedef changeset_post base; - - changeset_post (emitter_type& e, ostream& os, schema_format f) - : common (e, os, f) {} - - virtual void - traverse (sema_rel::changeset& m) - { - // Traverse named entities in the reverse order. This way we - // drop them in the order opposite to creating. - // - for (sema_rel::changeset::names_iterator begin (m.names_begin ()), - end (m.names_end ()); begin != end;) - dispatch (*--end); - } - - void - pass (unsigned short p) - { - pass_ = p; - } - - protected: - unsigned short pass_; - }; - - // - // Schema version table. - // - - struct version_table: common - { - typedef version_table base; - - version_table (emitter_type& e, ostream& os, schema_format f) - : common (e, os, f), - table_ (options.schema_version_table ()[db]), - qt_ (quote_id (table_)), - qs_ (quote_string (options.schema_name ()[db])), - qn_ (quote_id ("name")), - qv_ (quote_id ("version")), - qm_ (quote_id ("migration")) - { - } - - // Create the version table if it doesn't exist. - // - virtual void - create_table () {} - - // Remove the version entry. Called after the DROP statements. - // - virtual void - drop () - { - pre_statement (); - - os << "DELETE FROM " << qt_ << endl - << " WHERE " << qn_ << " = " << qs_ << endl; - - post_statement (); - } - - // Set the version. Called after the CREATE statements. - // - virtual void - create (sema_rel::version) {} - - // Set the version and migration state to true. Called after - // the pre migration statements. - // - virtual void - migrate_pre (sema_rel::version v) - { - pre_statement (); - - os << "UPDATE " << qt_ << endl - << " SET " << qv_ << " = " << v << ", " << qm_ << " = 1" << endl - << " WHERE " << qn_ << " = " << qs_ << endl; - - post_statement (); - } - - // Set migration state to false. Called after the post migration - // statements. - // - virtual void - migrate_post () - { - pre_statement (); - - os << "UPDATE " << qt_ << endl - << " SET " << qm_ << " = 0" << endl - << " WHERE " << qn_ << " = " << qs_ << endl; - - post_statement (); - } - - protected: - sema_rel::qname table_; - string qt_; // Quoted table. - string qs_; // Quoted schema name string. - string qn_; // Quoted name column. - string qv_; // Quoted version column. - string qm_; // Quoted migration column. - }; - - // - // SQL output. - // - - struct sql_emitter: emitter, virtual context - { - typedef sql_emitter base; - - virtual void - pre () - { - first_ = true; - } - - virtual void - line (const std::string& l) - { - if (first_ && !l.empty ()) - first_ = false; - else - os << endl; - - os << l; - } - - virtual void - post () - { - if (!first_) // Ignore empty statements. - os << ';' << endl - << endl; - } - - protected: - bool first_; - }; - - struct sql_file: virtual context - { - typedef sql_file base; - - virtual void - prologue () - { - } - - virtual void - epilogue () - { - } - }; - } -} - -#endif // ODB_RELATIONAL_SCHEMA_HXX -- cgit v1.1