diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2011-11-28 15:50:14 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2011-11-28 15:50:14 -0500 |
commit | 73ff4327d5c47f8e0480de4bc9f520c4338a63da (patch) | |
tree | d46e70ce9b229aaba74f377d173f6f05503416a6 /alembic | |
parent | 5d475742ee412e2c6fb261d935cf0e947c21a063 (diff) | |
download | alembic-73ff4327d5c47f8e0480de4bc9f520c4338a63da.tar.gz |
- rename autogenerate_metadata to target_metadata, autogenerate_sqlalchemy_prefix
to sqlalchemy_module_prefix
- add create_check_constraint() directive
Diffstat (limited to 'alembic')
-rw-r--r-- | alembic/autogenerate.py | 4 | ||||
-rw-r--r-- | alembic/context.py | 36 | ||||
-rw-r--r-- | alembic/op.py | 50 | ||||
-rw-r--r-- | alembic/templates/generic/env.py | 6 | ||||
-rw-r--r-- | alembic/templates/multidb/env.py | 6 | ||||
-rw-r--r-- | alembic/templates/pylons/env.py | 6 |
6 files changed, 86 insertions, 22 deletions
diff --git a/alembic/autogenerate.py b/alembic/autogenerate.py index b6811fa..bae14af 100644 --- a/alembic/autogenerate.py +++ b/alembic/autogenerate.py @@ -14,7 +14,7 @@ log = logging.getLogger(__name__) # top level def produce_migration_diffs(template_args, imports): - metadata = _context_opts['autogenerate_metadata'] + metadata = _context_opts['target_metadata'] if metadata is None: raise util.CommandError( "Can't proceed with --autogenerate option; environment " @@ -347,7 +347,7 @@ def _modify_col(tname, cname, return text def _autogenerate_prefix(): - return _context_opts['autogenerate_sqlalchemy_prefix'] or '' + return _context_opts['sqlalchemy_module_prefix'] or '' def _render_column(column, autogen_context): opts = [] diff --git a/alembic/context.py b/alembic/context.py index 0ac9cb9..51a060e 100644 --- a/alembic/context.py +++ b/alembic/context.py @@ -309,12 +309,12 @@ def configure( output_buffer=None, starting_rev=None, tag=None, - autogenerate_metadata=None, + target_metadata=None, compare_type=False, compare_server_default=False, upgrade_token="upgrades", downgrade_token="downgrades", - autogenerate_sqlalchemy_prefix="sa.", + sqlalchemy_module_prefix="sa.", ): """Configure the migration environment. @@ -351,11 +351,12 @@ def configure( ``--sql`` mode. :param tag: a string tag for usage by custom ``env.py`` scripts. Set via the ``--tag`` option, can be overridden here. - :param autogenerate_metadata: a :class:`sqlalchemy.schema.MetaData` object that + :param target_metadata: a :class:`sqlalchemy.schema.MetaData` object that will be consulted if the ``--autogenerate`` option is passed to the "alembic revision" command. The tables present will be compared against what is locally available on the target :class:`~sqlalchemy.engine.base.Connection` to produce candidate upgrade/downgrade operations. + :param compare_type: Indicates type comparison behavior during an autogenerate operation. Defaults to ``False`` which disables type comparison. Set to ``True`` to turn on default type comparison, which has varied accuracy depending @@ -371,7 +372,12 @@ def configure( # False if not, or None to allow the default implementation # to compare these types pass - + + ``inspected_column`` is a dictionary structure as returned by + :meth:`sqlalchemy.engine.reflection.Inspector.get_columns`, whereas + ``metadata_column`` is a :class:`sqlalchemy.schema.Column` from + the local model environment. + A return value of ``None`` indicates to allow default type comparison to proceed. @@ -392,19 +398,29 @@ def configure( # to compare these defaults pass + ``inspected_column`` is a dictionary structure as returned by + :meth:`sqlalchemy.engine.reflection.Inspector.get_columns`, whereas + ``metadata_column`` is a :class:`sqlalchemy.schema.Column` from + the local model environment. + A return value of ``None`` indicates to allow default server default comparison to proceed. Note that some backends such as Postgresql actually execute the two defaults on the database side to compare for equivalence. :param upgrade_token: when running "alembic revision" with the ``--autogenerate`` option, the text of the candidate upgrade operations will be present in this - template variable when script.py.mako is rendered. + template variable when ``script.py.mako`` is rendered. Defaults to ``upgrades``. :param downgrade_token: when running "alembic revision" with the ``--autogenerate`` option, the text of the candidate downgrade operations will be present in this - template variable when script.py.mako is rendered. - :param autogenerate_sqlalchemy_prefix: When autogenerate refers to SQLAlchemy + template variable when ``script.py.mako`` is rendered. Defaults to ``downgrades``. + + :param sqlalchemy_module_prefix: When autogenerate refers to SQLAlchemy :class:`~sqlalchemy.schema.Column` or type classes, this prefix will be used - (i.e. ``sa.Column("somename", sa.Integer)``) + (i.e. ``sa.Column("somename", sa.Integer)``) Defaults to "``sa.``". + Can be ``None`` to indicate no prefix. + Note that when dialect-specific types are rendered, autogenerate + will render them using the dialect module name, i.e. ``mssql.BIT()``, + ``postgresql.UUID()``. """ @@ -431,10 +447,10 @@ def configure( opts['starting_rev'] = starting_rev if tag: opts['tag'] = tag - opts['autogenerate_metadata'] = autogenerate_metadata + opts['target_metadata'] = target_metadata opts['upgrade_token'] = upgrade_token opts['downgrade_token'] = downgrade_token - opts['autogenerate_sqlalchemy_prefix'] = autogenerate_sqlalchemy_prefix + opts['sqlalchemy_module_prefix'] = sqlalchemy_module_prefix _context = Context( dialect, _script, connection, opts['fn'], diff --git a/alembic/op.py b/alembic/op.py index 227dc9c..848e40b 100644 --- a/alembic/op.py +++ b/alembic/op.py @@ -1,7 +1,7 @@ from alembic import util from alembic.ddl import impl from alembic.context import get_impl, get_context -from sqlalchemy.types import NULLTYPE +from sqlalchemy.types import NULLTYPE, Integer from sqlalchemy import schema, sql __all__ = sorted([ @@ -18,6 +18,7 @@ __all__ = sorted([ 'bulk_insert', 'rename_table', 'create_unique_constraint', + 'create_check_constraint', 'get_context', 'get_bind', 'execute']) @@ -47,6 +48,13 @@ def _unique_constraint(name, source, local_cols, **kw): t.append_constraint(uq) return uq +def _check_constraint(name, source, condition, **kw): + t = schema.Table(source, schema.MetaData(), + schema.Column('x', Integer)) + ck = schema.CheckConstraint(condition, name=name, **kw) + t.append_constraint(ck) + return ck + def _table(name, *columns, **kw): m = schema.MetaData() t = schema.Table(name, m, *columns, **kw) @@ -336,6 +344,46 @@ def create_unique_constraint(name, source, local_cols, **kw): **kw) ) +def create_check_constraint(name, source, condition, **kw): + """Issue a "create check constraint" instruction using the current change context. + + e.g.:: + + from alembic.op import create_check_constraint + from sqlalchemy.sql import column, func + + create_check_constraint( + "ck_user_name_len", + "user", + func.len(column('name')) > 5 + ) + + CHECK constraints are usually against a SQL expression, so ad-hoc + table metadata is usually needed. The function will convert the given + arguments into a :class:`sqlalchemy.schema.CheckConstraint` bound + to an anonymous table in order to emit the CREATE statement. + + :param name: Name of the check constraint. The name is necessary + so that an ALTER statement can be emitted. For setups that + use an automated naming scheme such as that described at + `NamingConventions <http://www.sqlalchemy.org/trac/wiki/UsageRecipes/NamingConventions>`_, + ``name`` here can be ``None``, as the event listener will + apply the name to the constraint object when it is associated + with the table. + :param source: String name of the source table. Currently + there is no support for dotted schema names. + :param condition: SQL expression that's the condition of the constraint. + Can be a string or SQLAlchemy expression language structure. + :param deferrable: optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE when + issuing DDL for this constraint. + :param initially: optional string. If set, emit INITIALLY <value> when issuing DDL + for this constraint. + + """ + get_impl().add_constraint( + _check_constraint(name, source, condition, **kw) + ) + def create_table(name, *columns, **kw): """Issue a "create table" instruction using the current change context. diff --git a/alembic/templates/generic/env.py b/alembic/templates/generic/env.py index 5095f0b..4bc6065 100644 --- a/alembic/templates/generic/env.py +++ b/alembic/templates/generic/env.py @@ -13,8 +13,8 @@ fileConfig(config.config_file_name) # add your model's MetaData object here # for 'autogenerate' support # from myapp import mymodel -# autogenerate_metadata = mymodel.Base.metadata -autogenerate_metadata = None +# target_metadata = mymodel.Base.metadata +target_metadata = None # other values from the config, defined by the needs of env.py, # can be acquired: @@ -55,7 +55,7 @@ def run_migrations_online(): connection = engine.connect() context.configure( connection=connection, - autogenerate_metadata=autogenerate_metadata + target_metadata=target_metadata ) trans = connection.begin() diff --git a/alembic/templates/multidb/env.py b/alembic/templates/multidb/env.py index 1ace59c..0db2a67 100644 --- a/alembic/templates/multidb/env.py +++ b/alembic/templates/multidb/env.py @@ -20,11 +20,11 @@ db_names = options.get_main_option('databases') # helpful here in case a "copy" of # a MetaData is needed. # from myapp import mymodel -# autogenerate_metadata = { +# target_metadata = { # 'engine1':mymodel.metadata1, # 'engine2':mymodel.metadata2 #} -autogenerate_metadata = {} +target_metadata = {} def run_migrations_offline(): """Run migrations in 'offline' mode. @@ -87,7 +87,7 @@ def run_migrations_online(): connection=rec['connection'], upgrade_token="%s_upgrades", downgrade_token="%s_downgrades", - autogenerate_metadata=autogenerate_metadata.get(name) + target_metadata=target_metadata.get(name) ) context.execute("--running migrations for engine %s" % name) context.run_migrations(engine=name) diff --git a/alembic/templates/pylons/env.py b/alembic/templates/pylons/env.py index da193f4..e9ea402 100644 --- a/alembic/templates/pylons/env.py +++ b/alembic/templates/pylons/env.py @@ -26,8 +26,8 @@ meta = __import__("%s.model.meta" % config['pylons.package']).model.meta # add your model's MetaData object here # for 'autogenerate' support # from myapp import mymodel -# autogenerate_metadata = mymodel.Base.metadata -autogenerate_metadata = None +# target_metadata = mymodel.Base.metadata +target_metadata = None def run_migrations_offline(): """Run migrations in 'offline' mode. @@ -55,7 +55,7 @@ def run_migrations_online(): connection = meta.engine.connect() context.configure( connection=connection, - autogenerate_metadata=autogenerate_metadata + target_metadata=target_metadata ) trans = connection.begin() try: |