Okay, we don't know that indexes are falsey, so let's make it clearer. Yeek!
[mediagoblin.git] / mediagoblin / db / migration_tools.py
index c0c7e9981e717329262bcbcbd79682fce79150e4..e39070c34160c1ba1b448a355433807448710589 100644 (file)
@@ -16,6 +16,7 @@
 
 from mediagoblin.tools.common import simple_printer
 from sqlalchemy import Table
+from sqlalchemy.sql import select
 
 class TableAlreadyExists(Exception):
     pass
@@ -29,7 +30,7 @@ class MigrationManager(object):
     to the latest migrations, etc.
     """
 
-    def __init__(self, name, models, migration_registry, session,
+    def __init__(self, name, models, foundations, migration_registry, session,
                  printer=simple_printer):
         """
         Args:
@@ -40,6 +41,7 @@ class MigrationManager(object):
         """
         self.name = unicode(name)
         self.models = models
+        self.foundations = foundations
         self.session = session
         self.migration_registry = migration_registry
         self._sorted_migrations = None
@@ -140,6 +142,18 @@ class MigrationManager(object):
             self.session.bind,
             tables=[model.__table__ for model in self.models])
 
+    def populate_table_foundations(self):
+        """
+        Create the table foundations (default rows) as layed out in FOUNDATIONS
+            in mediagoblin.db.models
+        """
+        for Model, rows in self.foundations.items():
+            self.printer(u'   + Laying foundations for %s table\n' % 
+                (Model.__name__))
+            for parameters in rows:
+                new_row = Model(**parameters)
+                self.session.add(new_row)
+
     def create_new_migration_record(self):
         """
         Create a new migration record for this migration set
@@ -175,8 +189,7 @@ class MigrationManager(object):
         if self.name == u'__main__':
             return u"main mediagoblin tables"
         else:
-            # TODO: Use the friendlier media manager "human readable" name
-            return u'media type "%s"' % self.name
+            return u'plugin "%s"' % self.name
 
     def init_or_migrate(self):
         """
@@ -203,9 +216,9 @@ class MigrationManager(object):
 
             self.init_tables()
             # auto-set at latest migration number
-            self.create_new_migration_record()  
-            
+            self.create_new_migration_record()
             self.printer(u"done.\n")
+            self.populate_table_foundations()
             self.set_current_migration()
             return u'inited'
 
@@ -274,3 +287,35 @@ def inspect_table(metadata, table_name):
     """Simple helper to get a ref to an already existing table"""
     return Table(table_name, metadata, autoload=True,
                  autoload_with=metadata.bind)
+
+def replace_table_hack(db, old_table, replacement_table):
+    """
+    A function to fully replace a current table with a new one for migrati-
+    -ons. This is necessary because some changes are made tricky in some situa-
+    -tion, for example, dropping a boolean column in sqlite is impossible w/o
+    this method
+
+        :param old_table            A ref to the old table, gotten through 
+                                    inspect_table
+
+        :param replacement_table    A ref to the new table, gotten through
+                                    inspect_table
+
+    Users are encouraged to sqlalchemy-migrate replace table solutions, unless
+    that is not possible... in which case, this solution works,
+    at least for sqlite.
+    """
+    surviving_columns = replacement_table.columns.keys()
+    old_table_name = old_table.name
+    for row in db.execute(select(
+        [column for column in old_table.columns
+            if column.name in surviving_columns])):
+
+        db.execute(replacement_table.insert().values(**row))
+    db.commit()
+
+    old_table.drop()
+    db.commit()
+
+    replacement_table.rename(old_table_name)
+    db.commit()