From bb111ac2fdff909ed0f91d6f1f65c05aaf984936 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 5 Apr 2013 12:27:59 +0200 Subject: Add NOT NULL column without default value initially as NULL --- odb/relational/mssql/schema.cxx | 23 ++++++++------- odb/relational/oracle/schema.cxx | 13 +++++---- odb/relational/pgsql/schema.cxx | 6 ++-- odb/relational/schema.hxx | 63 +++++++++++++++++++++++++++++++--------- odb/relational/sqlite/schema.cxx | 14 +++++++-- 5 files changed, 82 insertions(+), 37 deletions(-) diff --git a/odb/relational/mssql/schema.cxx b/odb/relational/mssql/schema.cxx index 2db0c12..d1d892a 100644 --- a/odb/relational/mssql/schema.cxx +++ b/odb/relational/mssql/schema.cxx @@ -341,23 +341,21 @@ namespace relational alter_column (base const& x): base (x) {} virtual void - traverse (sema_rel::alter_column& ac) + traverse (sema_rel::column& c) { - assert (ac.null_altered ()); - // Relax (NULL) in pre and tighten (NOT NULL) in post. // - if (pre_ != ac.null ()) + if (pre_ != c.null ()) return; - using sema_rel::alter_table; - alter_table& at (static_cast (ac.scope ())); + using sema_rel::table; + table& at (static_cast (c.scope ())); pre_statement (); os << "ALTER TABLE " << quote_id (at.name ()) << endl << " ALTER COLUMN "; - alter (ac); + alter (c); os << endl; post_statement (); @@ -380,8 +378,11 @@ namespace relational alter_header (at.name ()); os << " ADD "; - instance c (emitter (), stream (), format_); - trav_rel::unames n (*c); + instance cc (emitter (), stream (), format_); + trav_rel::alter_column ac; // Override. + trav_rel::unames n; + n >> cc; + n >> ac; names (at, n); os << endl; @@ -415,8 +416,8 @@ namespace relational alter_header (at.name ()); os << " DROP COLUMN "; - instance c (emitter (), stream (), format_); - trav_rel::unames n (*c); + instance dc (emitter (), stream (), format_); + trav_rel::unames n (*dc); names (at, n); os << endl; diff --git a/odb/relational/oracle/schema.cxx b/odb/relational/oracle/schema.cxx index 024701c..9dc1921 100644 --- a/odb/relational/oracle/schema.cxx +++ b/odb/relational/oracle/schema.cxx @@ -349,13 +349,11 @@ namespace relational alter_column (base const& x): base (x) {} virtual void - traverse (sema_rel::alter_column& ac) + traverse (sema_rel::column& c) { - assert (ac.null_altered ()); - // Relax (NULL) in pre and tighten (NOT NULL) in post. // - if (pre_ != ac.null ()) + if (pre_ != c.null ()) return; if (first_) @@ -364,7 +362,7 @@ namespace relational os << "," << endl << " "; - os << quote_id (ac.name ()) << (ac.null () ? " NULL" : " NOT NULL"); + os << quote_id (c.name ()) << (c.null () ? " NULL" : " NOT NULL"); } }; entry alter_column_; @@ -386,7 +384,10 @@ namespace relational os << " ADD ("; instance cc (emitter (), stream (), format_); - trav_rel::unames n (*cc); + trav_rel::alter_column ac; // Override. + trav_rel::unames n; + n >> cc; + n >> ac; names (at, n); os << ")" << endl; diff --git a/odb/relational/pgsql/schema.cxx b/odb/relational/pgsql/schema.cxx index 7e0b7a5..575f8e4 100644 --- a/odb/relational/pgsql/schema.cxx +++ b/odb/relational/pgsql/schema.cxx @@ -215,10 +215,10 @@ namespace relational alter_column (base const& x): base (x) {} virtual void - alter (sema_rel::alter_column& ac) + alter (sema_rel::column& c) { - os << quote_id (ac.name ()) << " " << - (ac.null () ? "DROP" : "SET") << " NOT NULL"; + os << quote_id (c.name ()) << " " << + (c.null () ? "DROP" : "SET") << " NOT NULL"; } }; entry alter_column_; diff --git a/odb/relational/schema.hxx b/odb/relational/schema.hxx index fcb176f..32cac41 100644 --- a/odb/relational/schema.hxx +++ b/odb/relational/schema.hxx @@ -312,11 +312,13 @@ namespace relational create_column (emitter_type& e, ostream& os, schema_format f, + bool override_null = true, bool* first = 0) : common (e, os), format_ (f), first_ (first != 0 ? *first : first_data_), - first_data_ (true) + first_data_ (true), + override_null_ (override_null) { } @@ -326,7 +328,8 @@ namespace relational common (c), format_ (c.format_), first_ (&c.first_ != &c.first_data_ ? c.first_ : first_data_), - first_data_ (c.first_data_) + first_data_ (c.first_data_), + override_null_ (c.override_null_) { } @@ -410,10 +413,20 @@ namespace relational 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 << (c.null () ? " NULL" : " NOT NULL"); + os << (n ? " NULL" : " NOT NULL"); } virtual void @@ -431,6 +444,8 @@ namespace relational schema_format format_; bool& first_; bool first_data_; + bool add_; + bool override_null_; // Override NOT NULL in add_column. }; struct create_primary_key: trav_rel::primary_key, virtual context @@ -811,7 +826,9 @@ namespace relational // Migration. // - struct alter_column: trav_rel::alter_column, common + struct alter_column: trav_rel::alter_column, + trav_rel::add_column, + common { typedef alter_column base; @@ -825,7 +842,8 @@ namespace relational pre_ (pre), first_ (first != 0 ? *first : first_data_), first_data_ (true), - def_ (e, os, f) + fl_ (false), + def_ (e, os, f, fl_) { } @@ -837,7 +855,8 @@ namespace relational pre_ (c.pre_), first_ (&c.first_ != &c.first_data_ ? c.first_ : first_data_), first_data_ (c.first_data_), - def_ (common::e_, common::os_, c.format_) + fl_ (false), + def_ (common::e_, common::os_, c.format_, fl_) { } @@ -848,21 +867,19 @@ namespace relational } virtual void - alter (sema_rel::alter_column& ac) + alter (sema_rel::column& c) { // By default use the whole definition. // - def_->create (ac); + def_->create (c); } virtual void - traverse (sema_rel::alter_column& ac) + traverse (sema_rel::column& c) { - assert (ac.null_altered ()); - // Relax (NULL) in pre and tighten (NOT NULL) in post. // - if (pre_ != ac.null ()) + if (pre_ != c.null ()) return; if (first_) @@ -872,7 +889,24 @@ namespace relational os << " "; alter_header (); - alter (ac); + 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: @@ -880,6 +914,7 @@ namespace relational bool pre_; bool& first_; bool first_data_; + bool fl_; // (Im)perfect forwarding. instance def_; }; @@ -971,7 +1006,7 @@ namespace relational bool f (true); // Shared first flag. bool* pf (&f); // (Im)perfect forwarding. bool tl (true); // (Im)perfect forwarding. - instance cc (emitter (), stream (), format_, pf); + instance cc (emitter (), stream (), format_, tl, pf); instance ac (emitter (), stream (), format_, tl, pf); trav_rel::unames n; n >> cc; diff --git a/odb/relational/sqlite/schema.cxx b/odb/relational/sqlite/schema.cxx index 6d3cba4..9d3f859 100644 --- a/odb/relational/sqlite/schema.cxx +++ b/odb/relational/sqlite/schema.cxx @@ -21,7 +21,13 @@ namespace relational struct create_column: relational::create_column, context { - create_column (base const& x): base (x) {} + create_column (base const& x): base (x) + { + // In SQLite it is impossible to alter a column later, so we add + // it as is. + // + override_null_ = false; + } virtual void traverse (sema_rel::add_column& ac) @@ -118,9 +124,11 @@ namespace relational { // SQLite can only add a single column per ALTER TABLE statement. // - instance c (emitter (), stream (), format_); + instance cc (emitter (), stream (), format_); + trav_rel::alter_column ac; // Override. trav_rel::unames n; - n >> c; + n >> cc; + n >> ac; names (at, n); // SQLite does not support altering columns. -- cgit v1.1