aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2013-04-05 10:16:48 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2013-04-10 18:46:44 +0200
commit853d76b58e96aab4e6182cc1234652dfcdd74c14 (patch)
tree612e54f542dd3d6a11d8a8299f2c82f35e9e714e
parentc9dbc099d74d92b17724a24823aafe1fcc8ca7e7 (diff)
Generate alter column migration statements
-rw-r--r--odb/relational/mssql/schema.cxx53
-rw-r--r--odb/relational/mysql/schema.cxx12
-rw-r--r--odb/relational/oracle/schema.cxx65
-rw-r--r--odb/relational/pgsql/schema.cxx13
-rw-r--r--odb/relational/schema.hxx160
-rw-r--r--odb/relational/sqlite/schema.cxx11
6 files changed, 292 insertions, 22 deletions
diff --git a/odb/relational/mssql/schema.cxx b/odb/relational/mssql/schema.cxx
index 03406ce..2db0c12 100644
--- a/odb/relational/mssql/schema.cxx
+++ b/odb/relational/mssql/schema.cxx
@@ -336,6 +336,35 @@ namespace relational
};
entry<drop_index> drop_index_;
+ struct alter_column: relational::alter_column, context
+ {
+ alter_column (base const& x): base (x) {}
+
+ virtual void
+ traverse (sema_rel::alter_column& ac)
+ {
+ assert (ac.null_altered ());
+
+ // Relax (NULL) in pre and tighten (NOT NULL) in post.
+ //
+ if (pre_ != ac.null ())
+ return;
+
+ using sema_rel::alter_table;
+ alter_table& at (static_cast<alter_table&> (ac.scope ()));
+
+ pre_statement ();
+
+ os << "ALTER TABLE " << quote_id (at.name ()) << endl
+ << " ALTER COLUMN ";
+ alter (ac);
+ os << endl;
+
+ post_statement ();
+ }
+ };
+ entry<alter_column> alter_column_;
+
struct alter_table_pre: relational::alter_table_pre, context
{
alter_table_pre (base const& x): base (x) {}
@@ -352,13 +381,21 @@ namespace relational
os << " ADD ";
instance<create_column> c (emitter (), stream (), format_);
- trav_rel::unames n;
- n >> c;
+ trav_rel::unames n (*c);
names (at, n);
os << endl;
post_statement ();
}
+
+ // For ALTER COLUMN, SQL Server can only have one per ALTER TABLE.
+ //
+ {
+ bool tl (true); // (Im)perfect forwarding.
+ instance<alter_column> ac (emitter (), stream (), format_, tl);
+ trav_rel::unames n (*ac);
+ names (at, n);
+ }
}
};
entry<alter_table_pre> alter_table_pre_;
@@ -379,13 +416,21 @@ namespace relational
os << " DROP COLUMN ";
instance<drop_column> c (emitter (), stream (), format_);
- trav_rel::unames n;
- n >> c;
+ trav_rel::unames n (*c);
names (at, n);
os << endl;
post_statement ();
}
+
+ // For ALTER COLUMN, SQL Server can only have one per ALTER TABLE.
+ //
+ {
+ bool fl (false); // (Im)perfect forwarding.
+ instance<alter_column> ac (emitter (), stream (), format_, fl);
+ trav_rel::unames n (*ac);
+ names (at, n);
+ }
}
};
entry<alter_table_post> alter_table_post_;
diff --git a/odb/relational/mysql/schema.cxx b/odb/relational/mysql/schema.cxx
index c3f7571..6ce619b 100644
--- a/odb/relational/mysql/schema.cxx
+++ b/odb/relational/mysql/schema.cxx
@@ -367,6 +367,18 @@ namespace relational
}
};
entry<drop_index> drop_index_;
+
+ struct alter_column: relational::alter_column, context
+ {
+ alter_column (base const& x): base (x) {}
+
+ virtual void
+ alter_header ()
+ {
+ os << "MODIFY COLUMN ";
+ }
+ };
+ entry<alter_column> alter_column_;
}
}
}
diff --git a/odb/relational/oracle/schema.cxx b/odb/relational/oracle/schema.cxx
index 34ede1c..024701c 100644
--- a/odb/relational/oracle/schema.cxx
+++ b/odb/relational/oracle/schema.cxx
@@ -344,6 +344,31 @@ namespace relational
};
entry<drop_index> drop_index_;
+ struct alter_column: relational::alter_column, context
+ {
+ alter_column (base const& x): base (x) {}
+
+ virtual void
+ traverse (sema_rel::alter_column& ac)
+ {
+ assert (ac.null_altered ());
+
+ // Relax (NULL) in pre and tighten (NOT NULL) in post.
+ //
+ if (pre_ != ac.null ())
+ return;
+
+ if (first_)
+ first_ = false;
+ else
+ os << "," << endl
+ << " ";
+
+ os << quote_id (ac.name ()) << (ac.null () ? " NULL" : " NOT NULL");
+ }
+ };
+ entry<alter_column> alter_column_;
+
struct alter_table_pre: relational::alter_table_pre, context
{
alter_table_pre (base const& x): base (x) {}
@@ -360,9 +385,23 @@ namespace relational
alter_header (at.name ());
os << " ADD (";
- instance<create_column> c (emitter (), stream (), format_);
- trav_rel::unames n;
- n >> c;
+ instance<create_column> cc (emitter (), stream (), format_);
+ trav_rel::unames n (*cc);
+ names (at, n);
+ os << ")" << endl;
+
+ post_statement ();
+ }
+
+ if (check_alter_null (at, true))
+ {
+ pre_statement ();
+ alter_header (at.name ());
+ os << " MODIFY (";
+
+ bool tl (true); // (Im)perfect forwarding.
+ instance<alter_column> ac (emitter (), stream (), format_, tl);
+ trav_rel::unames n (*ac);
names (at, n);
os << ")" << endl;
@@ -388,9 +427,23 @@ namespace relational
alter_header (at.name ());
os << " DROP (";
- instance<drop_column> c (emitter (), stream (), format_);
- trav_rel::unames n;
- n >> c;
+ instance<drop_column> dc (emitter (), stream (), format_);
+ trav_rel::unames n (*dc);
+ names (at, n);
+ os << ")" << endl;
+
+ post_statement ();
+ }
+
+ if (check_alter_null (at, false))
+ {
+ pre_statement ();
+ alter_header (at.name ());
+ os << " MODIFY (";
+
+ bool fl (false); // (Im)perfect forwarding.
+ instance<alter_column> ac (emitter (), stream (), format_, fl);
+ trav_rel::unames n (*ac);
names (at, n);
os << ")" << endl;
diff --git a/odb/relational/pgsql/schema.cxx b/odb/relational/pgsql/schema.cxx
index efe9b40..7e0b7a5 100644
--- a/odb/relational/pgsql/schema.cxx
+++ b/odb/relational/pgsql/schema.cxx
@@ -209,6 +209,19 @@ namespace relational
}
};
entry<create_index> create_index_;
+
+ struct alter_column: relational::alter_column, context
+ {
+ alter_column (base const& x): base (x) {}
+
+ virtual void
+ alter (sema_rel::alter_column& ac)
+ {
+ os << quote_id (ac.name ()) << " " <<
+ (ac.null () ? "DROP" : "SET") << " NOT NULL";
+ }
+ };
+ entry<alter_column> alter_column_;
}
}
}
diff --git a/odb/relational/schema.hxx b/odb/relational/schema.hxx
index b0d70df..69e8089 100644
--- a/odb/relational/schema.hxx
+++ b/odb/relational/schema.hxx
@@ -64,8 +64,24 @@ namespace relational
{
typedef drop_column base;
- drop_column (emitter_type& e, ostream& os, schema_format f)
- : common (e, os), format_ (f), first_ (true)
+ drop_column (emitter_type& e,
+ ostream& os,
+ schema_format f,
+ bool* first = 0)
+ : common (e, os),
+ format_ (f),
+ first_ (first != 0 ? *first : first_data_),
+ first_data_ (true)
+ {
+ }
+
+ drop_column (drop_column const& c)
+ : root_context (), // @@ -Wextra
+ context (),
+ common (c),
+ format_ (c.format_),
+ first_ (&c.first_ != &c.first_data_ ? c.first_ : first_data_),
+ first_data_ (c.first_data_)
{
}
@@ -92,7 +108,8 @@ namespace relational
protected:
schema_format format_;
- bool first_;
+ bool& first_;
+ bool first_data_;
};
// Currently only used in migration.
@@ -292,8 +309,24 @@ namespace relational
{
typedef create_column base;
- create_column (emitter_type& e, ostream& os, schema_format f)
- : common (e, os), format_ (f), first_ (true)
+ create_column (emitter_type& e,
+ ostream& os,
+ schema_format f,
+ bool* first = 0)
+ : common (e, os),
+ format_ (f),
+ first_ (first != 0 ? *first : first_data_),
+ first_data_ (true)
+ {
+ }
+
+ create_column (create_column const& c)
+ : root_context (), // @@ -Wextra
+ context (),
+ common (c),
+ format_ (c.format_),
+ first_ (&c.first_ != &c.first_data_ ? c.first_ : first_data_),
+ first_data_ (c.first_data_)
{
}
@@ -394,7 +427,8 @@ namespace relational
protected:
schema_format format_;
- bool first_;
+ bool& first_;
+ bool first_data_;
};
struct create_primary_key: trav_rel::primary_key, virtual context
@@ -775,6 +809,78 @@ namespace relational
// Migration.
//
+ struct alter_column: trav_rel::alter_column, common
+ {
+ typedef alter_column base;
+
+ alter_column (emitter_type& e,
+ ostream& os,
+ schema_format f,
+ bool pre,
+ bool* first = 0)
+ : common (e, os),
+ format_ (f),
+ pre_ (pre),
+ first_ (first != 0 ? *first : first_data_),
+ first_data_ (true),
+ def_ (e, os, f)
+ {
+ }
+
+ alter_column (alter_column const& c)
+ : root_context (), // @@ -Wextra
+ context (),
+ common (c),
+ format_ (c.format_),
+ 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_)
+ {
+ }
+
+ virtual void
+ alter_header ()
+ {
+ os << "ALTER COLUMN ";
+ }
+
+ virtual void
+ alter (sema_rel::alter_column& ac)
+ {
+ // By default use the whole definition.
+ //
+ def_->create (ac);
+ }
+
+ virtual void
+ traverse (sema_rel::alter_column& ac)
+ {
+ assert (ac.null_altered ());
+
+ // Relax (NULL) in pre and tighten (NOT NULL) in post.
+ //
+ if (pre_ != ac.null ())
+ return;
+
+ if (first_)
+ first_ = false;
+ else
+ os << "," << endl;
+
+ os << " ";
+ alter_header ();
+ alter (ac);
+ }
+
+ protected:
+ schema_format format_;
+ bool pre_;
+ bool& first_;
+ bool first_data_;
+ instance<create_column> def_;
+ };
+
struct alter_table_common: trav_rel::alter_table, common
{
alter_table_common (emitter_type& e, ostream& os, schema_format f)
@@ -796,6 +902,24 @@ namespace relational
return 0;
}
+ sema_rel::alter_column*
+ check_alter_null (sema_rel::alter_table& at, bool v)
+ {
+ using sema_rel::alter_column;
+
+ for (sema_rel::alter_table::names_iterator i (at.names_begin ());
+ i != at.names_end (); ++i)
+ {
+ if (alter_column* ac = dynamic_cast<alter_column*> (&i->nameable ()))
+ {
+ if (ac->null_altered () && ac->null () == v)
+ return ac;
+ }
+ }
+
+ return 0;
+ }
+
virtual void
alter_header (sema_rel::qname const& table)
{
@@ -829,7 +953,8 @@ namespace relational
virtual bool
check (sema_rel::alter_table& at)
{
- return check<sema_rel::add_column> (at);
+ return check<sema_rel::add_column> (at) ||
+ check_alter_null (at, true);
}
virtual void
@@ -841,9 +966,14 @@ namespace relational
pre_statement ();
alter_header (at.name ());
- instance<create_column> c (emitter (), stream (), format_);
+ 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<alter_column> ac (emitter (), stream (), format_, tl, pf);
trav_rel::unames n;
- n >> c;
+ n >> cc;
+ n >> ac;
names (at, n);
os << endl;
@@ -933,7 +1063,8 @@ namespace relational
virtual bool
check (sema_rel::alter_table& at)
{
- return check<sema_rel::drop_column> (at);
+ return check<sema_rel::drop_column> (at) ||
+ check_alter_null (at, false);
}
virtual void
@@ -945,9 +1076,14 @@ namespace relational
pre_statement ();
alter_header (at.name ());
- instance<drop_column> c (emitter (), stream (), format_);
+ bool f (true); // Shared first flag.
+ bool* pf (&f); // (Im)perfect forwarding.
+ bool fl (false); // (Im)perfect forwarding.
+ instance<drop_column> dc (emitter (), stream (), format_, pf);
+ instance<alter_column> ac (emitter (), stream (), format_, fl, pf);
trav_rel::unames n;
- n >> c;
+ n >> dc;
+ n >> ac;
names (at, n);
os << endl;
diff --git a/odb/relational/sqlite/schema.cxx b/odb/relational/sqlite/schema.cxx
index ac19328..6d3cba4 100644
--- a/odb/relational/sqlite/schema.cxx
+++ b/odb/relational/sqlite/schema.cxx
@@ -122,6 +122,17 @@ namespace relational
trav_rel::unames n;
n >> c;
names (at, n);
+
+ // SQLite does not support altering columns.
+ //
+ if (sema_rel::alter_column* ac = check<sema_rel::alter_column> (at))
+ {
+ cerr << "error: SQLite does not support altering of columns"
+ << endl;
+ cerr << "info: first altered column is '" << ac->name () <<
+ "' in table '" << at.name () << "'" << endl;
+ throw operation_failed ();
+ }
}
};
entry<alter_table_pre> alter_table_pre_;