summaryrefslogtreecommitdiff
path: root/odb/relational/mssql/schema.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'odb/relational/mssql/schema.cxx')
-rw-r--r--odb/relational/mssql/schema.cxx76
1 files changed, 73 insertions, 3 deletions
diff --git a/odb/relational/mssql/schema.cxx b/odb/relational/mssql/schema.cxx
index 52d36ed..91bb891 100644
--- a/odb/relational/mssql/schema.cxx
+++ b/odb/relational/mssql/schema.cxx
@@ -45,18 +45,88 @@ namespace relational
drop_table (base const& x): base (x) {}
virtual void
- drop (sema_rel::qname const& table)
+ traverse (sema_rel::table&);
+
+ private:
+ friend class drop_foreign_key;
+ set<qname> tables_; // Set of tables we would have already dropped.
+ };
+ entry<drop_table> drop_table_;
+
+ struct drop_foreign_key: trav_rel::foreign_key, relational::common
+ {
+ drop_foreign_key (drop_table& dt)
+ : common (dt.emitter (), dt.stream ()), dt_ (dt)
+ {
+ }
+
+ virtual void
+ traverse (sema_rel::foreign_key& fk)
+ {
+ // Deferred constraints are not supported by SQL Server.
+ //
+ if (fk.deferred ())
+ return;
+
+ // 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.
+ //
+ sema_rel::qname const& rt (fk.referenced_table ());
+ sema_rel::table& t (dynamic_cast<sema_rel::table&> (fk.scope ()));
+ sema_rel::model& m (dynamic_cast<sema_rel::model&> (t.scope ()));
+
+ if (dt_.tables_.find (rt) != dt_.tables_.end () ||
+ m.find (rt) == m.names_end ())
+ {
+
+ // In SQL Server, foreign key names are schema-global. Make them
+ // unique by prefixing the key name with table name. Note, however,
+ // that they cannot have a schema.
+ //
+ string n (t.name ().uname () + "_" + fk.name ());
+
+ pre_statement ();
+ os << "IF OBJECT_ID(" << quote_string (n) << ", " <<
+ quote_string ("F") << ") IS NOT NULL" << endl
+ << " ALTER TABLE " << quote_id (t.name ()) << " DROP" << endl
+ << " CONSTRAINT " << quote_id (n) << endl;
+ post_statement ();
+ }
+ }
+
+ private:
+ drop_table& dt_;
+ };
+
+ void drop_table::
+ traverse (sema_rel::table& t)
+ {
+ qname const& table (t.name ());
+
+ if (pass_ == 1)
+ {
+ // Drop constraints.
+ //
+ tables_.insert (table); // Add it before to cover self-refs.
+ drop_foreign_key fk (*this);
+ trav_rel::unames n (fk);
+ names (t, n);
+ }
+ else if (pass_ == 2)
{
// SQL Server has no IF EXISTS conditional for dropping table.
// The following approach appears to be the recommended way to
// drop a table if it exists.
//
+ pre_statement ();
os << "IF OBJECT_ID(" << quote_string (table.string ()) <<
", " << quote_string ("U") << ") IS NOT NULL" << endl
<< " DROP TABLE " << quote_id (table) << endl;
+ post_statement ();
}
- };
- entry<drop_table> drop_table_;
+ }
//
// Create.