aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2013-04-05 12:27:59 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2013-04-10 18:46:44 +0200
commitbb111ac2fdff909ed0f91d6f1f65c05aaf984936 (patch)
treeac681b67c848fade47538b27bf8c179c068b5433
parentca6ab8a1a4eedf6f751f5ba2205cd57ca37fad80 (diff)
Add NOT NULL column without default value initially as NULL
-rw-r--r--odb/relational/mssql/schema.cxx23
-rw-r--r--odb/relational/oracle/schema.cxx13
-rw-r--r--odb/relational/pgsql/schema.cxx6
-rw-r--r--odb/relational/schema.hxx63
-rw-r--r--odb/relational/sqlite/schema.cxx14
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<alter_table&> (ac.scope ()));
+ using sema_rel::table;
+ table& at (static_cast<table&> (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<create_column> c (emitter (), stream (), format_);
- trav_rel::unames n (*c);
+ instance<create_column> 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<drop_column> c (emitter (), stream (), format_);
- trav_rel::unames n (*c);
+ instance<drop_column> 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> alter_column_;
@@ -386,7 +384,10 @@ namespace relational
os << " ADD (";
instance<create_column> 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> 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<sema_rel::add_column> () &&
+ !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<sema_rel::column&> (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<sema_rel::column&> (ac));
}
protected:
@@ -880,6 +914,7 @@ namespace relational
bool pre_;
bool& first_;
bool first_data_;
+ bool fl_; // (Im)perfect forwarding.
instance<create_column> 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<create_column> cc (emitter (), stream (), format_, pf);
+ instance<create_column> cc (emitter (), stream (), format_, tl, pf);
instance<alter_column> 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<create_column> c (emitter (), stream (), format_);
+ instance<create_column> 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.