From 09a8867edd9bf32ec594bea869cf691ba86a9f2f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Domen=20Ko=C5=BEar?= <domen@dev.si>
Date: Sat, 5 Feb 2011 14:16:00 +0100
Subject: [PATCH 01/16] fixes #106

---
 docs/changelog.rst              |  3 +++
 migrate/versioning/script/py.py | 13 +++++++------
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/docs/changelog.rst b/docs/changelog.rst
index c1a2eeb..8b1e31a 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -13,7 +13,10 @@ Fixed bugs
 ******************
 
 - updated tests for Python 2.7
+- repository keyword in :func:`api.version_control` can also be unicode
 - added if main condition for manage.py script
+- make :func:`migrate.changeset.constraint.ForeignKeyConstraint.autoname`
+  work with SQLAlchemy 0.5 and 0.6
 - fixed case sensitivity in setup.py dependencies
 - moved :mod:`migrate.changeset.exceptions` and :mod:`migrate.versioning.exceptions`
   to :mod:`migrate.exceptions`
diff --git a/migrate/versioning/script/py.py b/migrate/versioning/script/py.py
index ed5b87e..5089d18 100644
--- a/migrate/versioning/script/py.py
+++ b/migrate/versioning/script/py.py
@@ -4,6 +4,7 @@
 import shutil
 import warnings
 import logging
+import inspect
 from StringIO import StringIO
 
 import migrate
@@ -136,12 +137,12 @@ class PythonScript(base.BaseScript):
         funcname = base.operations[op]
         script_func = self._func(funcname)
 
-        try:
-            script_func(engine)
-        except TypeError:
-            warnings.warn("upgrade/downgrade functions must accept engine"
-                " parameter (since version > 0.5.4)", MigrateDeprecationWarning)
-            raise
+        # check for old way of using engine
+        if not inspect.getargspec(script_func).args:
+            raise TypeError("upgrade/downgrade functions must accept engine"
+                " parameter (since version 0.5.4)")
+
+        script_func(engine)
 
     @property
     def module(self):

From 1b37b76d2e7d8632b03161775edb68c48a504e8c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Domen=20Ko=C5=BEar?= <domen@dev.si>
Date: Sat, 5 Feb 2011 14:25:25 +0100
Subject: [PATCH 02/16] fixes #107

---
 docs/changelog.rst             | 7 ++++---
 migrate/versioning/genmodel.py | 8 ++++----
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/docs/changelog.rst b/docs/changelog.rst
index 8b1e31a..f07cadb 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -20,11 +20,12 @@ Fixed bugs
 - fixed case sensitivity in setup.py dependencies
 - moved :mod:`migrate.changeset.exceptions` and :mod:`migrate.versioning.exceptions`
   to :mod:`migrate.exceptions`
-- cleared up test output and improved testing of deprecation warnings.
+- cleared up test output and improved testing of deprecation warnings. 
 - some documentation fixes
-- fixed bug with column dropping in sqlite (issue 96)
+- #107: fixed syntax error in genmodel.py 
+- #96: fixed bug with column dropping in sqlite
+- #94: fixed bug that prevented non-unique indexes being created
 - fixed bug with column dropping involving foreign keys
-- fixed bug that prevented non-unique indexes being created (issue 94)
 - fixed bug when dropping columns with unique constraints in sqlite
 - rewrite of the schema diff internals, now supporting column
   differences in additon to missing columns and tables.
diff --git a/migrate/versioning/genmodel.py b/migrate/versioning/genmodel.py
index 5a43437..b3449b6 100644
--- a/migrate/versioning/genmodel.py
+++ b/migrate/versioning/genmodel.py
@@ -170,11 +170,11 @@ class ModelGenerator(object):
                         modelTable, col.name))
             for modelCol, databaseCol, modelDecl, databaseDecl in diffDecl:
                 upgradeCommands.append(
-                    'assert False, "Can\'t alter columns: %s:%s=>%s"',
-                    modelTable, modelCol.name, databaseCol.name)
+                    'assert False, "Can\'t alter columns: %s:%s=>%s"' % (
+                    modelTable, modelCol.name, databaseCol.name))
                 downgradeCommands.append(
-                    'assert False, "Can\'t alter columns: %s:%s=>%s"',
-                    modelTable, modelCol.name, databaseCol.name)
+                    'assert False, "Can\'t alter columns: %s:%s=>%s"' % (
+                    modelTable, modelCol.name, databaseCol.name))
         pre_command = '    meta.bind = migrate_engine'
 
         return (

From 7bccd681a0bbdcc82b61cd982dad061ab97d28a6 Mon Sep 17 00:00:00 2001
From: Jan Dittberner <jan.dittberner@googlemail.com>
Date: Sat, 5 Feb 2011 14:27:26 +0100
Subject: [PATCH 03/16] use mirrored copy of kinterbasedb to cope with
 SourceForge reliability problems

---
 test-req.pip | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test-req.pip b/test-req.pip
index 58011eb..46c0196 100644
--- a/test-req.pip
+++ b/test-req.pip
@@ -9,6 +9,6 @@ pytz
 http://initd.org/psycopg/tarballs/psycopg2-2.2.2.tar.gz
 pysqlite
 mysql-python
-http://downloads.sourceforge.net/firebird/kinterbasdb-3.3.0.tar.bz2
+http://jenkins.gnuviech-server.de/userContent/kinterbasdb-3.3.0.tar.bz2
 virtualenv
 unittest2

From b2db52ff4e974cd3011acc1ea126ea6dfdc6f29e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Domen=20Ko=C5=BEar?= <domen@dev.si>
Date: Sat, 5 Feb 2011 18:19:37 +0100
Subject: [PATCH 04/16] fix py2.4 and py2.5

---
 migrate/versioning/script/py.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/migrate/versioning/script/py.py b/migrate/versioning/script/py.py
index 5089d18..35fe4aa 100644
--- a/migrate/versioning/script/py.py
+++ b/migrate/versioning/script/py.py
@@ -138,7 +138,7 @@ class PythonScript(base.BaseScript):
         script_func = self._func(funcname)
 
         # check for old way of using engine
-        if not inspect.getargspec(script_func).args:
+        if not inspect.getargspec(script_func)[0]:
             raise TypeError("upgrade/downgrade functions must accept engine"
                 " parameter (since version 0.5.4)")
 

From 9c9fe2fc2425e5fe251415d622eb5b6639584b37 Mon Sep 17 00:00:00 2001
From: Chris Withers <chris@simplistix.co.uk>
Date: Thu, 10 Feb 2011 15:15:22 +0000
Subject: [PATCH 05/16] Only alter the SA objects after running the visitor, so
 the visitor may inspect

---
 migrate/changeset/schema.py | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/migrate/changeset/schema.py b/migrate/changeset/schema.py
index ef8dd85..00e1a3e 100644
--- a/migrate/changeset/schema.py
+++ b/migrate/changeset/schema.py
@@ -559,11 +559,10 @@ populated with defaults
         if table is not None:
             self.table = table
         engine = self.table.bind
-        if self.alter_metadata:
-            self.remove_from_table(self.table, unset_table=False)
         visitorcallable = get_engine_visitor(engine, 'columndropper')
         engine._run_visitor(visitorcallable, self, connection, **kwargs)
         if self.alter_metadata:
+            self.remove_from_table(self.table, unset_table=False)
             self.table = None
         return self
 

From f749919240a4cf32cc6d6c1962276191ecbd8f41 Mon Sep 17 00:00:00 2001
From: Chris Withers <chris@simplistix.co.uk>
Date: Thu, 10 Feb 2011 15:16:15 +0000
Subject: [PATCH 06/16] These drop indexes appear to only be for firebird. Once
 firebird is fixed, they're not needed.

---
 migrate/tests/changeset/test_changeset.py | 2 --
 1 file changed, 2 deletions(-)

diff --git a/migrate/tests/changeset/test_changeset.py b/migrate/tests/changeset/test_changeset.py
index 5c06ef2..4f4291d 100644
--- a/migrate/tests/changeset/test_changeset.py
+++ b/migrate/tests/changeset/test_changeset.py
@@ -262,7 +262,6 @@ class TestAddDropColumn(fixture.DB):
 
         self._check_index(False)
 
-        Index('ix_data', col).drop(bind=self.engine)
         col.drop()
         
     @fixture.usedb()
@@ -284,7 +283,6 @@ class TestAddDropColumn(fixture.DB):
 
         self._check_index(True)
 
-        Index('ix_data', col).drop(bind=self.engine)
         col.drop()
         
     @fixture.usedb()

From b1745bee521b36b3c2e3ca0b224f8cfdbf085400 Mon Sep 17 00:00:00 2001
From: Chris Withers <chris@simplistix.co.uk>
Date: Thu, 10 Feb 2011 15:16:35 +0000
Subject: [PATCH 07/16] firebird can only drop named foreign keys

---
 migrate/tests/changeset/test_changeset.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/migrate/tests/changeset/test_changeset.py b/migrate/tests/changeset/test_changeset.py
index 4f4291d..1218b54 100644
--- a/migrate/tests/changeset/test_changeset.py
+++ b/migrate/tests/changeset/test_changeset.py
@@ -422,7 +422,8 @@ class TestAddDropColumn(fixture.DB):
             Column('r1', Integer),
             Column('r2', Integer),
             ForeignKeyConstraint(['r1','r2'],
-                                 [reftable.c.id,reftable.c.jd])
+                                 [reftable.c.id,reftable.c.jd],
+                                 name='test_fk')
             )
         self.table.create()
 

From 500cb6f5df5cbdf19b6155820e6f51e672e64649 Mon Sep 17 00:00:00 2001
From: Chris Withers <chris@simplistix.co.uk>
Date: Thu, 10 Feb 2011 15:17:28 +0000
Subject: [PATCH 08/16] fix sqlite column dropper now that the table is only
 modified after the visitor is run

---
 migrate/changeset/databases/sqlite.py | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/migrate/changeset/databases/sqlite.py b/migrate/changeset/databases/sqlite.py
index 66a8f5a..01e48ef 100644
--- a/migrate/changeset/databases/sqlite.py
+++ b/migrate/changeset/databases/sqlite.py
@@ -80,10 +80,19 @@ class SQLiteColumnDropper(SQLiteHelper, ansisql.ANSIColumnDropper):
     """SQLite ColumnDropper"""
 
     def _modify_table(self, table, column, delta):
+        
         columns = ' ,'.join(map(self.preparer.format_column, table.columns))
         return 'INSERT INTO %(table_name)s SELECT ' + columns + \
             ' from migration_tmp'
 
+    def visit_column(self,column):
+        # For SQLite, we *have* to remove the column so the table
+        # is re-created properly.
+        # This violates the alter_metadata settting, but that
+        # is going away...
+        column.remove_from_table(column.table,unset_table=False)
+        super(SQLiteColumnDropper,self).visit_column(column)
+
 
 class SQLiteSchemaChanger(SQLiteHelper, ansisql.ANSISchemaChanger):
     """SQLite SchemaChanger"""

From c80120da555f41a9b2eff9310b5d4bda1d0c149e Mon Sep 17 00:00:00 2001
From: Chris Withers <chris@simplistix.co.uk>
Date: Thu, 10 Feb 2011 15:19:00 +0000
Subject: [PATCH 09/16] work around firebird's insistence that indexes and
 constraints are dropped before columns that are references by them.

---
 migrate/changeset/databases/firebird.py | 28 ++++++++++++++++++-------
 1 file changed, 21 insertions(+), 7 deletions(-)

diff --git a/migrate/changeset/databases/firebird.py b/migrate/changeset/databases/firebird.py
index f880035..b296fa5 100644
--- a/migrate/changeset/databases/firebird.py
+++ b/migrate/changeset/databases/firebird.py
@@ -2,7 +2,7 @@
    Firebird database specific implementations of changeset classes.
 """
 from sqlalchemy.databases import firebird as sa_base
-
+from sqlalchemy.schema import PrimaryKeyConstraint
 from migrate import exceptions
 from migrate.changeset import ansisql, SQLA_06
 
@@ -27,13 +27,27 @@ class FBColumnDropper(ansisql.ANSIColumnDropper):
             if column.table.primary_key.columns.contains_column(column):
                 column.table.primary_key.drop()
                 # TODO: recreate primary key if it references more than this column
-        if column.unique or getattr(column, 'unique_name', None):
-            for cons in column.table.constraints:
-                if cons.contains_column(column):
-                    cons.drop()
-                    # TODO: recreate unique constraint if it refenrences more than this column
 
-        table = self.start_alter_table(column)
+        for index in column.table.indexes:
+            # "column in index.columns" causes problems as all
+            # column objects compare equal and return a SQL expression
+            if column.name in [col.name for col in index.columns]:
+                index.drop()
+                # TODO: recreate index if it references more than this column
+        
+        for cons in column.table.constraints:
+            if isinstance(cons,PrimaryKeyConstraint):
+                # will be deleted only when the column its on
+                # is deleted!
+                continue
+            if cons.contains_column(column) and cons.name:
+                self.start_alter_table(column)
+                self.append("DROP CONSTRAINT ")
+                self.append(self.preparer.format_constraint(cons))
+                self.execute()
+            # TODO: recreate unique constraint if it refenrences more than this column
+
+        self.start_alter_table(column)
         self.append('DROP %s' % self.preparer.format_column(column))
         self.execute()
 

From b5a02cb7cfc1b6c032df3fed7002e968c1932162 Mon Sep 17 00:00:00 2001
From: Chris Withers <chris@simplistix.co.uk>
Date: Thu, 10 Feb 2011 16:49:20 +0000
Subject: [PATCH 10/16] remove the alter_metadata feature

---
 docs/changelog.rst                        |  3 +-
 migrate/changeset/databases/sqlite.py     |  4 +-
 migrate/changeset/schema.py               | 87 ++++++-----------------
 migrate/tests/changeset/test_changeset.py | 68 +++++-------------
 4 files changed, 42 insertions(+), 120 deletions(-)

diff --git a/docs/changelog.rst b/docs/changelog.rst
index f07cadb..732f703 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -7,7 +7,7 @@ Features
 - implemented columns adding with unique constraints for sqlite
 - implemented adding unique and foreign key constraints to columns
   for sqlite
-
+- remove experimental `alter_metadata` parameter
 
 Fixed bugs
 ******************
@@ -31,6 +31,7 @@ Fixed bugs
   differences in additon to missing columns and tables.
 - fixed bug when passing empty list in
   :func:`migrate.versioning.shell.main` failed 
+- #108: Fixed issues with firebird support.
 
 0.6 (11.07.2010)
 ---------------------------
diff --git a/migrate/changeset/databases/sqlite.py b/migrate/changeset/databases/sqlite.py
index 01e48ef..447412d 100644
--- a/migrate/changeset/databases/sqlite.py
+++ b/migrate/changeset/databases/sqlite.py
@@ -86,10 +86,8 @@ class SQLiteColumnDropper(SQLiteHelper, ansisql.ANSIColumnDropper):
             ' from migration_tmp'
 
     def visit_column(self,column):
-        # For SQLite, we *have* to remove the column so the table
+        # For SQLite, we *have* to remove the column here so the table
         # is re-created properly.
-        # This violates the alter_metadata settting, but that
-        # is going away...
         column.remove_from_table(column.table,unset_table=False)
         super(SQLiteColumnDropper,self).visit_column(column)
 
diff --git a/migrate/changeset/schema.py b/migrate/changeset/schema.py
index 00e1a3e..8c4f458 100644
--- a/migrate/changeset/schema.py
+++ b/migrate/changeset/schema.py
@@ -29,9 +29,6 @@ __all__ = [
     'ColumnDelta',
 ]
 
-DEFAULT_ALTER_METADATA = True
-
-
 def create_column(column, table=None, *p, **kw):
     """Create a column, given the table.
     
@@ -109,19 +106,11 @@ def alter_column(*p, **k):
       The :class:`~sqlalchemy.engine.base.Engine` to use for table
       reflection and schema alterations.
     
-    :param alter_metadata:
-      If `True`, which is the default, the
-      :class:`~sqlalchemy.schema.Column` will also modified.
-      If `False`, the :class:`~sqlalchemy.schema.Column` will be left
-      as it was.
-    
     :returns: A :class:`ColumnDelta` instance representing the change.
 
     
     """
     
-    k.setdefault('alter_metadata', DEFAULT_ALTER_METADATA)
-
     if 'table' not in k and isinstance(p[0], sqlalchemy.Column):
         k['table'] = p[0].table
     if 'engine' not in k:
@@ -188,11 +177,10 @@ class ColumnDelta(DictMixin, sqlalchemy.schema.SchemaItem):
         :param table: Table at which current Column should be bound to.\
         If table name is given, reflection will be used.
         :type table: string or Table instance
-        :param alter_metadata: If True, it will apply changes to metadata.
-        :type alter_metadata: bool
-        :param metadata: If `alter_metadata` is true, \
-        metadata is used to reflect table names into
-        :type metadata: :class:`MetaData` instance
+        
+        :param metadata: A :class:`MetaData` instance to store
+                         reflected table names
+                         
         :param engine: When reflecting tables, either engine or metadata must \
         be specified to acquire engine object.
         :type engine: :class:`Engine` instance
@@ -213,7 +201,6 @@ class ColumnDelta(DictMixin, sqlalchemy.schema.SchemaItem):
     __visit_name__ = 'column'
 
     def __init__(self, *p, **kw):
-        self.alter_metadata = kw.pop("alter_metadata", False)
         self.meta = kw.pop("metadata", None)
         self.engine = kw.pop("engine", None)
 
@@ -237,8 +224,7 @@ class ColumnDelta(DictMixin, sqlalchemy.schema.SchemaItem):
         self.apply_diffs(diffs)
 
     def __repr__(self):
-        return '<ColumnDelta altermetadata=%r, %s>' % (self.alter_metadata,
-            super(ColumnDelta, self).__repr__())
+        return '<ColumnDelta %s>' % super(ColumnDelta, self).__repr__()
 
     def __getitem__(self, key):
         if key not in self.keys():
@@ -314,7 +300,7 @@ class ColumnDelta(DictMixin, sqlalchemy.schema.SchemaItem):
             self.result_column.type = self.result_column.type()
 
         # add column to the table
-        if self.table is not None and self.alter_metadata:
+        if self.table is not None:
             self.result_column.add_to_table(self.table)
 
     def are_column_types_eq(self, old_type, new_type):
@@ -376,38 +362,27 @@ class ColumnDelta(DictMixin, sqlalchemy.schema.SchemaItem):
 
     def _set_table(self, table):
         if isinstance(table, basestring):
-            if self.alter_metadata:
-                if not self.meta:
-                    raise ValueError("metadata must be specified for table"
-                        " reflection when using alter_metadata")
-                meta = self.meta
-                if self.engine:
-                    meta.bind = self.engine
-            else:
-                if not self.engine and not self.meta:
-                    raise ValueError("engine or metadata must be specified"
-                        " to reflect tables")
-                if not self.engine:
-                    self.engine = self.meta.bind
-                meta = sqlalchemy.MetaData(bind=self.engine)
+            if not self.engine and not self.meta:
+                raise ValueError("engine or metadata must be specified"
+                                 " to reflect tables")
+            if not self.meta:
+                self.meta = sqlalchemy.MetaData()
+            meta = self.meta
+            if self.engine:
+                meta.bind = self.engine
             self._table = sqlalchemy.Table(table, meta, autoload=True)
         elif isinstance(table, sqlalchemy.Table):
             self._table = table
-            if not self.alter_metadata:
-                self._table.meta = sqlalchemy.MetaData(bind=self._table.bind)
 
     def _get_result_column(self):
         return getattr(self, '_result_column', None)
 
     def _set_result_column(self, column):
-        """Set Column to Table based on alter_metadata evaluation."""
+        """Set Column to Table."""
         self.process_column(column)
         if not hasattr(self, 'current_name'):
             self.current_name = column.name
-        if self.alter_metadata:
-            self._result_column = column
-        else:
-            self._result_column = column.copy_fixed()
+        self._result_column = column
 
     table = property(_get_table, _set_table)
     result_column = property(_get_result_column, _set_result_column)
@@ -456,22 +431,18 @@ class ChangesetTable(object):
 
         :param name: New name of the table.
         :type name: string
-        :param alter_metadata: If True, table will be removed from metadata
-        :type alter_metadata: bool
         :param connection: reuse connection istead of creating new one.
         :type connection: :class:`sqlalchemy.engine.base.Connection` instance
         """
-        self.alter_metadata = kwargs.pop('alter_metadata', DEFAULT_ALTER_METADATA)
         engine = self.bind
         self.new_name = name
         visitorcallable = get_engine_visitor(engine, 'schemachanger')
         run_single_visitor(engine, visitorcallable, self, connection, **kwargs)
 
         # Fix metadata registration
-        if self.alter_metadata:
-            self.name = name
-            self.deregister()
-            self._set_parent(self.metadata)
+        self.name = name
+        self.deregister()
+        self._set_parent(self.metadata)
 
     def _meta_key(self):
         return sqlalchemy.schema._get_table_key(self.name, self.schema)
@@ -510,7 +481,6 @@ class ChangesetColumn(object):
 `~migrate.changeset.constraint.UniqueConstraint` on this column.
         :param primary_key_name: Creates :class:\
 `~migrate.changeset.constraint.PrimaryKeyConstraint` on this column.
-        :param alter_metadata: If True, column will be added to table object.
         :param populate_default: If True, created column will be \
 populated with defaults
         :param connection: reuse connection istead of creating new one.
@@ -518,22 +488,19 @@ populated with defaults
         :type index_name: string
         :type unique_name: string
         :type primary_key_name: string
-        :type alter_metadata: bool
         :type populate_default: bool
         :type connection: :class:`sqlalchemy.engine.base.Connection` instance
 
         :returns: self
         """
         self.populate_default = populate_default
-        self.alter_metadata = kwargs.pop('alter_metadata', DEFAULT_ALTER_METADATA)
         self.index_name = index_name
         self.unique_name = unique_name
         self.primary_key_name = primary_key_name
         for cons in ('index_name', 'unique_name', 'primary_key_name'):
             self._check_sanity_constraints(cons)
 
-        if self.alter_metadata:
-            self.add_to_table(table)
+        self.add_to_table(table)
         engine = self.table.bind
         visitorcallable = get_engine_visitor(engine, 'columngenerator')
         engine._run_visitor(visitorcallable, self, connection, **kwargs)
@@ -550,20 +517,16 @@ populated with defaults
 
         ``ALTER TABLE DROP COLUMN``, for most databases.
 
-        :param alter_metadata: If True, column will be removed from table object.
-        :type alter_metadata: bool
         :param connection: reuse connection istead of creating new one.
         :type connection: :class:`sqlalchemy.engine.base.Connection` instance
         """
-        self.alter_metadata = kwargs.pop('alter_metadata', DEFAULT_ALTER_METADATA)
         if table is not None:
             self.table = table
         engine = self.table.bind
         visitorcallable = get_engine_visitor(engine, 'columndropper')
         engine._run_visitor(visitorcallable, self, connection, **kwargs)
-        if self.alter_metadata:
-            self.remove_from_table(self.table, unset_table=False)
-            self.table = None
+        self.remove_from_table(self.table, unset_table=False)
+        self.table = None
         return self
 
     def add_to_table(self, table):
@@ -642,18 +605,14 @@ class ChangesetIndex(object):
 
         :param name: New name of the Index.
         :type name: string
-        :param alter_metadata: If True, Index object will be altered.
-        :type alter_metadata: bool
         :param connection: reuse connection istead of creating new one.
         :type connection: :class:`sqlalchemy.engine.base.Connection` instance
         """
-        self.alter_metadata = kwargs.pop('alter_metadata', DEFAULT_ALTER_METADATA)
         engine = self.table.bind
         self.new_name = name
         visitorcallable = get_engine_visitor(engine, 'schemachanger')
         engine._run_visitor(visitorcallable, self, connection, **kwargs)
-        if self.alter_metadata:
-            self.name = name
+        self.name = name
 
 
 class ChangesetDefaultClause(object):
diff --git a/migrate/tests/changeset/test_changeset.py b/migrate/tests/changeset/test_changeset.py
index 1218b54..ce6fdcc 100644
--- a/migrate/tests/changeset/test_changeset.py
+++ b/migrate/tests/changeset/test_changeset.py
@@ -704,20 +704,6 @@ class TestColumnChange(fixture.DB):
         finally:
             cw.__exit__()
             
-    @fixture.usedb()
-    def test_alter_metadata(self):
-        """Test if alter_metadata is respected"""
-
-        self.table.c.data.alter(type=String(100))
-
-        self.assert_(isinstance(self.table.c.data.type, String))
-        self.assertEqual(self.table.c.data.type.length, 100)
-
-        # nothing should change
-        self.table.c.data.alter(type=String(200),alter_metadata=False)
-        self.assert_(isinstance(self.table.c.data.type, String))
-        self.assertEqual(self.table.c.data.type.length, 100)
-
     @fixture.usedb()
     def test_alter_returns_delta(self):
         """Test if alter constructs return delta"""
@@ -741,8 +727,7 @@ class TestColumnChange(fixture.DB):
         kw = dict(nullable=False,
                  server_default='foobar',
                  name='data_new',
-                 type=String(50),
-                 alter_metadata=True)
+                 type=String(50))
         if self.engine.name == 'firebird':
             del kw['nullable']
         self.table.c.data.alter(**kw)
@@ -805,13 +790,15 @@ class TestColumnDelta(fixture.DB):
 
     def test_deltas_two_columns(self):
         """Testing ColumnDelta with two columns"""
-        col_orig = self.mkcol(primary_key=True)
-        col_new = self.mkcol(name='ids', primary_key=True)
-        self.verify([], col_orig, col_orig)
-        self.verify(['name'], col_orig, col_orig, 'ids')
-        self.verify(['name'], col_orig, col_orig, name='ids')
-        self.verify(['name'], col_orig, col_new)
-        self.verify(['name', 'type'], col_orig, col_new, type=String)
+        col_orig = lambda :self.mkcol(primary_key=True)
+        col_new = lambda: self.mkcol(name='ids', primary_key=True)
+        # we have to create new columns, since comparing the ColumnDelta
+        # will apply differences
+        self.verify([], col_orig(), col_orig())
+        self.verify(['name'], col_orig(), col_orig(), 'ids')
+        self.verify(['name'], col_orig(), col_orig(), name='ids')
+        self.verify(['name'], col_orig(), col_new())
+        self.verify(['name', 'type'], col_orig(), col_new(), type=String)
 
         # Type comparisons
         self.verify([], self.mkcol(type=String), self.mkcol(type=String))
@@ -839,23 +826,16 @@ class TestColumnDelta(fixture.DB):
         self.verify([], self.mkcol(server_default='foobar'), self.mkcol('id', String, DefaultClause('foobar')))
         self.verify(['type'], self.mkcol(server_default='foobar'), self.mkcol('id', Text, DefaultClause('foobar')))
 
-        # test alter_metadata
         col = self.mkcol(server_default='foobar')
-        self.verify(['type'], col, self.mkcol('id', Text, DefaultClause('foobar')), alter_metadata=True)
+        self.verify(['type'], col, self.mkcol('id', Text, DefaultClause('foobar')))
         self.assert_(isinstance(col.type, Text))
 
         col = self.mkcol()
-        self.verify(['name', 'server_default', 'type'], col, self.mkcol('beep', Text, DefaultClause('foobar')), alter_metadata=True)
+        self.verify(['name', 'server_default', 'type'], col, self.mkcol('beep', Text, DefaultClause('foobar')))
         self.assert_(isinstance(col.type, Text))
         self.assertEqual(col.name, 'beep')
         self.assertEqual(col.server_default.arg, 'foobar')
 
-        col = self.mkcol()
-        self.verify(['name', 'server_default', 'type'], col, self.mkcol('beep', Text, DefaultClause('foobar')), alter_metadata=False)
-        self.assertFalse(isinstance(col.type, Text))
-        self.assertNotEqual(col.name, 'beep')
-        self.assertFalse(col.server_default)
-
     @fixture.usedb()
     def test_deltas_zero_columns(self):
         """Testing ColumnDelta with zero columns"""
@@ -866,30 +846,20 @@ class TestColumnDelta(fixture.DB):
         self.verify(['type'], 'ids', table=self.table.name, type=String(80), engine=self.engine)
         self.verify(['type'], 'ids', table=self.table.name, type=String(80), metadata=self.meta)
 
-        # check if alter_metadata is respected
         self.meta.clear()
-        delta = self.verify(['type'], 'ids', table=self.table.name, type=String(80), alter_metadata=True, metadata=self.meta)
+        delta = self.verify(['type'], 'ids', table=self.table.name, type=String(80), metadata=self.meta)
         self.assert_(self.table.name in self.meta)
         self.assertEqual(delta.result_column.type.length, 80)
         self.assertEqual(self.meta.tables.get(self.table.name).c.ids.type.length, 80)
 
-        self.meta.clear()
-        self.verify(['type'], 'ids', table=self.table.name, type=String(80), alter_metadata=False, engine=self.engine)
-        self.assert_(self.table.name not in self.meta)
-
-        self.meta.clear()
-        self.verify(['type'], 'ids', table=self.table.name, type=String(80), alter_metadata=False, metadata=self.meta)
-        self.assert_(self.table.name not in self.meta)
-
         # test defaults
         self.meta.clear()
-        self.verify(['server_default'], 'ids', table=self.table.name, server_default='foobar', alter_metadata=True, metadata=self.meta)
+        self.verify(['server_default'], 'ids', table=self.table.name, server_default='foobar', metadata=self.meta)
         self.meta.tables.get(self.table.name).c.ids.server_default.arg == 'foobar'
 
         # test missing parameters
         self.assertRaises(ValueError, ColumnDelta, table=self.table.name)
-        self.assertRaises(ValueError, ColumnDelta, 'ids', table=self.table.name, alter_metadata=True)
-        self.assertRaises(ValueError, ColumnDelta, 'ids', table=self.table.name, alter_metadata=False)
+        self.assertRaises(ValueError, ColumnDelta, 'ids', table=self.table.name)
 
     def test_deltas_one_column(self):
         """Testing ColumnDelta with one column"""
@@ -907,17 +877,11 @@ class TestColumnDelta(fixture.DB):
         self.assertEquals(delta.get('name'), 'blah')
         self.assertEquals(delta.current_name, 'id')
 
-        # check if alter_metadata is respected
         col_orig = self.mkcol(primary_key=True)
-        self.verify(['name', 'type'], col_orig, name='id12', type=Text, alter_metadata=True)
+        self.verify(['name', 'type'], col_orig, name='id12', type=Text)
         self.assert_(isinstance(col_orig.type, Text))
         self.assertEqual(col_orig.name, 'id12')
 
-        col_orig = self.mkcol(primary_key=True)
-        self.verify(['name', 'type'], col_orig, name='id12', type=Text, alter_metadata=False)
-        self.assert_(isinstance(col_orig.type, String))
-        self.assertEqual(col_orig.name, 'id')
-
         # test server default
         col_orig = self.mkcol(primary_key=True)
         delta = self.verify(['server_default'], col_orig, DefaultClause('foobar'))

From cda65c38b53ec0a0ffca0bcd30c675386e24c450 Mon Sep 17 00:00:00 2001
From: Chris Withers <chris@simplistix.co.uk>
Date: Thu, 10 Feb 2011 17:02:42 +0000
Subject: [PATCH 11/16] try to get firebird stuff working with 0.6.6

---
 migrate/changeset/databases/firebird.py | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/migrate/changeset/databases/firebird.py b/migrate/changeset/databases/firebird.py
index b296fa5..675666c 100644
--- a/migrate/changeset/databases/firebird.py
+++ b/migrate/changeset/databases/firebird.py
@@ -40,7 +40,12 @@ class FBColumnDropper(ansisql.ANSIColumnDropper):
                 # will be deleted only when the column its on
                 # is deleted!
                 continue
-            if cons.contains_column(column) and cons.name:
+
+            if SQLA_06:
+                should_drop = column.name in cons.columns
+            else:
+                should_drop = cons.contains_column(column) and cons.name
+            if should_drop:
                 self.start_alter_table(column)
                 self.append("DROP CONSTRAINT ")
                 self.append(self.preparer.format_constraint(cons))

From 0645c2fc9a052d8ef52b4120c7383aa6c6cf5b6f Mon Sep 17 00:00:00 2001
From: Chris Withers <chris@simplistix.co.uk>
Date: Fri, 11 Feb 2011 10:27:39 +0000
Subject: [PATCH 12/16] Bring back alter_metadata on ColumnDelta: it seems
 intertwined with a lot of the tests. So, it's a private API now...

---
 migrate/changeset/schema.py               | 52 +++++++++++++++++------
 migrate/tests/changeset/test_changeset.py | 33 +++++++-------
 2 files changed, 56 insertions(+), 29 deletions(-)

diff --git a/migrate/changeset/schema.py b/migrate/changeset/schema.py
index 8c4f458..75cd3fd 100644
--- a/migrate/changeset/schema.py
+++ b/migrate/changeset/schema.py
@@ -124,6 +124,12 @@ def alter_column(*p, **k):
             MigrateDeprecationWarning
             )
     engine = k['engine']
+
+    # enough tests seem to break when metadata is always altered
+    # that this crutch has to be left in until they can be sorted
+    # out
+    k['alter_metadata']=True
+    
     delta = ColumnDelta(*p, **k)
 
     visitorcallable = get_engine_visitor(engine, 'schemachanger')
@@ -201,6 +207,11 @@ class ColumnDelta(DictMixin, sqlalchemy.schema.SchemaItem):
     __visit_name__ = 'column'
 
     def __init__(self, *p, **kw):
+        # 'alter_metadata' is not a public api. It exists purely
+        # as a crutch until the tests that fail when 'alter_metadata'
+        # behaviour always happens can be sorted out
+        self.alter_metadata = kw.pop("alter_metadata", False)
+        
         self.meta = kw.pop("metadata", None)
         self.engine = kw.pop("engine", None)
 
@@ -224,8 +235,11 @@ class ColumnDelta(DictMixin, sqlalchemy.schema.SchemaItem):
         self.apply_diffs(diffs)
 
     def __repr__(self):
-        return '<ColumnDelta %s>' % super(ColumnDelta, self).__repr__()
-
+        return '<ColumnDelta altermetadata=%r, %s>' % (
+            self.alter_metadata,
+            super(ColumnDelta, self).__repr__()
+            )
+    
     def __getitem__(self, key):
         if key not in self.keys():
             raise KeyError("No such diff key, available: %s" % self.diffs )
@@ -300,7 +314,7 @@ class ColumnDelta(DictMixin, sqlalchemy.schema.SchemaItem):
             self.result_column.type = self.result_column.type()
 
         # add column to the table
-        if self.table is not None:
+        if self.table is not None and self.alter_metadata:
             self.result_column.add_to_table(self.table)
 
     def are_column_types_eq(self, old_type, new_type):
@@ -362,27 +376,37 @@ class ColumnDelta(DictMixin, sqlalchemy.schema.SchemaItem):
 
     def _set_table(self, table):
         if isinstance(table, basestring):
-            if not self.engine and not self.meta:
-                raise ValueError("engine or metadata must be specified"
-                                 " to reflect tables")
-            if not self.meta:
-                self.meta = sqlalchemy.MetaData()
-            meta = self.meta
-            if self.engine:
-                meta.bind = self.engine
+            if self.alter_metadata:
+                if not self.meta:
+                    raise ValueError("metadata must be specified for table"
+                        " reflection when using alter_metadata")
+                meta = self.meta
+                if self.engine:
+                    meta.bind = self.engine
+            else:
+                if not self.engine and not self.meta:
+                    raise ValueError("engine or metadata must be specified"
+                        " to reflect tables")
+                if not self.engine:
+                    self.engine = self.meta.bind
+                meta = sqlalchemy.MetaData(bind=self.engine)
             self._table = sqlalchemy.Table(table, meta, autoload=True)
         elif isinstance(table, sqlalchemy.Table):
             self._table = table
-
+            if not self.alter_metadata:
+                self._table.meta = sqlalchemy.MetaData(bind=self._table.bind)
     def _get_result_column(self):
         return getattr(self, '_result_column', None)
 
     def _set_result_column(self, column):
-        """Set Column to Table."""
+        """Set Column to Table based on alter_metadata evaluation."""
         self.process_column(column)
         if not hasattr(self, 'current_name'):
             self.current_name = column.name
-        self._result_column = column
+        if self.alter_metadata:
+            self._result_column = column
+        else:
+            self._result_column = column.copy_fixed()
 
     table = property(_get_table, _set_table)
     result_column = property(_get_result_column, _set_result_column)
diff --git a/migrate/tests/changeset/test_changeset.py b/migrate/tests/changeset/test_changeset.py
index ce6fdcc..2b50922 100644
--- a/migrate/tests/changeset/test_changeset.py
+++ b/migrate/tests/changeset/test_changeset.py
@@ -790,15 +790,13 @@ class TestColumnDelta(fixture.DB):
 
     def test_deltas_two_columns(self):
         """Testing ColumnDelta with two columns"""
-        col_orig = lambda :self.mkcol(primary_key=True)
-        col_new = lambda: self.mkcol(name='ids', primary_key=True)
-        # we have to create new columns, since comparing the ColumnDelta
-        # will apply differences
-        self.verify([], col_orig(), col_orig())
-        self.verify(['name'], col_orig(), col_orig(), 'ids')
-        self.verify(['name'], col_orig(), col_orig(), name='ids')
-        self.verify(['name'], col_orig(), col_new())
-        self.verify(['name', 'type'], col_orig(), col_new(), type=String)
+        col_orig = self.mkcol(primary_key=True)
+        col_new = self.mkcol(name='ids', primary_key=True)
+        self.verify([], col_orig, col_orig)
+        self.verify(['name'], col_orig, col_orig, 'ids')
+        self.verify(['name'], col_orig, col_orig, name='ids')
+        self.verify(['name'], col_orig, col_new)
+        self.verify(['name', 'type'], col_orig, col_new, type=String)
 
         # Type comparisons
         self.verify([], self.mkcol(type=String), self.mkcol(type=String))
@@ -827,11 +825,12 @@ class TestColumnDelta(fixture.DB):
         self.verify(['type'], self.mkcol(server_default='foobar'), self.mkcol('id', Text, DefaultClause('foobar')))
 
         col = self.mkcol(server_default='foobar')
-        self.verify(['type'], col, self.mkcol('id', Text, DefaultClause('foobar')))
+        self.verify(['type'], col, self.mkcol('id', Text, DefaultClause('foobar')), alter_metadata=True)
         self.assert_(isinstance(col.type, Text))
 
         col = self.mkcol()
-        self.verify(['name', 'server_default', 'type'], col, self.mkcol('beep', Text, DefaultClause('foobar')))
+        self.verify(['name', 'server_default', 'type'], col, self.mkcol('beep', Text, DefaultClause('foobar')),
+                    alter_metadata=True)
         self.assert_(isinstance(col.type, Text))
         self.assertEqual(col.name, 'beep')
         self.assertEqual(col.server_default.arg, 'foobar')
@@ -847,19 +846,23 @@ class TestColumnDelta(fixture.DB):
         self.verify(['type'], 'ids', table=self.table.name, type=String(80), metadata=self.meta)
 
         self.meta.clear()
-        delta = self.verify(['type'], 'ids', table=self.table.name, type=String(80), metadata=self.meta)
+        delta = self.verify(['type'], 'ids', table=self.table.name, type=String(80), metadata=self.meta,
+                            alter_metadata=True)
         self.assert_(self.table.name in self.meta)
         self.assertEqual(delta.result_column.type.length, 80)
         self.assertEqual(self.meta.tables.get(self.table.name).c.ids.type.length, 80)
 
         # test defaults
         self.meta.clear()
-        self.verify(['server_default'], 'ids', table=self.table.name, server_default='foobar', metadata=self.meta)
+        self.verify(['server_default'], 'ids', table=self.table.name, server_default='foobar',
+                    metadata=self.meta,
+                    alter_metadata=True)
         self.meta.tables.get(self.table.name).c.ids.server_default.arg == 'foobar'
 
         # test missing parameters
         self.assertRaises(ValueError, ColumnDelta, table=self.table.name)
-        self.assertRaises(ValueError, ColumnDelta, 'ids', table=self.table.name)
+        self.assertRaises(ValueError, ColumnDelta, 'ids', table=self.table.name, alter_metadata=True)
+        self.assertRaises(ValueError, ColumnDelta, 'ids', table=self.table.name, alter_metadata=False)
 
     def test_deltas_one_column(self):
         """Testing ColumnDelta with one column"""
@@ -878,7 +881,7 @@ class TestColumnDelta(fixture.DB):
         self.assertEquals(delta.current_name, 'id')
 
         col_orig = self.mkcol(primary_key=True)
-        self.verify(['name', 'type'], col_orig, name='id12', type=Text)
+        self.verify(['name', 'type'], col_orig, name='id12', type=Text, alter_metadata=True)
         self.assert_(isinstance(col_orig.type, Text))
         self.assertEqual(col_orig.name, 'id12')
 

From 45c37c9188dcdc4b014b7a46ff94222c6b8979d3 Mon Sep 17 00:00:00 2001
From: Jan Dittberner <jan.dittberner@googlemail.com>
Date: Fri, 11 Feb 2011 21:11:17 +0100
Subject: [PATCH 13/16] finalize changelog for 0.6.1

---
 docs/changelog.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/changelog.rst b/docs/changelog.rst
index 732f703..24d09bf 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -1,4 +1,4 @@
-0.6.1 (xxxxxxx)
+0.6.1 (2011-02-11)
 ---------------------------
 
 Features

From cd653ddfe25410cfc319eb34f4b36a46e6d8361c Mon Sep 17 00:00:00 2001
From: Jan Dittberner <jan.dittberner@googlemail.com>
Date: Fri, 11 Feb 2011 21:12:15 +0100
Subject: [PATCH 14/16] Added tag v0.6.1 for changeset c2526dce0768

---
 .hgtags | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.hgtags b/.hgtags
index f0a7f11..a6e8fed 100644
--- a/.hgtags
+++ b/.hgtags
@@ -1 +1,2 @@
 cb01bf174b05b1590258d6c996b89f60ebd88e5a v0.6
+c2526dce0768f11e6bf88afb641a6a9058fa685c v0.6.1

From 21bbca280a9e5e24661b0e3526e842ac6ce56eec Mon Sep 17 00:00:00 2001
From: Jan Dittberner <jan.dittberner@googlemail.com>
Date: Fri, 11 Feb 2011 21:30:04 +0100
Subject: [PATCH 15/16] update version in docs/conf.py

---
 docs/conf.py | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/docs/conf.py b/docs/conf.py
index e49fcce..be9220d 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -47,16 +47,16 @@ master_doc = 'index'
 
 # General information about the project.
 project = u'SQLAlchemy Migrate'
-copyright = u'2010, Evan Rosson, Jan Dittberner, Domen Kožar'
+copyright = u'2011, Evan Rosson, Jan Dittberner, Domen Kožar, Chris Withers'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
 # built documents.
 #
 # The short X.Y version.
-version = '0.6'
+version = '0.6.1'
 # The full version, including alpha/beta/rc tags.
-release = '0.6'
+release = '0.6.1'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.

From 4e601ff4054b89f71fb914324e2aa8888084e7e9 Mon Sep 17 00:00:00 2001
From: Jan Dittberner <jan.dittberner@googlemail.com>
Date: Fri, 11 Feb 2011 23:25:18 +0100
Subject: [PATCH 16/16] start next iteration

---
 docs/changelog.rst | 3 +++
 docs/conf.py       | 4 ++--
 setup.py           | 2 +-
 3 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/docs/changelog.rst b/docs/changelog.rst
index 24d09bf..7bbb9a8 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -1,3 +1,6 @@
+0.6.2 (XXXX-XX-XX)
+---------------------------
+
 0.6.1 (2011-02-11)
 ---------------------------
 
diff --git a/docs/conf.py b/docs/conf.py
index be9220d..b8346bb 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -54,9 +54,9 @@ copyright = u'2011, Evan Rosson, Jan Dittberner, Domen Kožar, Chris Withers'
 # built documents.
 #
 # The short X.Y version.
-version = '0.6.1'
+version = '0.6.2'
 # The full version, including alpha/beta/rc tags.
-release = '0.6.1'
+release = '0.6.2'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/setup.py b/setup.py
index c0b6f6b..a2daa11 100644
--- a/setup.py
+++ b/setup.py
@@ -15,7 +15,7 @@ readme_file = open(os.path.join(os.path.dirname(os.path.abspath(__file__)),
 
 setup(
     name = "sqlalchemy-migrate",
-    version = "0.6.1",
+    version = "0.6.2",
     packages = find_packages(exclude=["migrate.tests*"]),
     include_package_data = True,
     description = "Database schema migration for SQLAlchemy",