Search code examples
alembic

Is it possible to deactivate the autogenerated Drop?


I'm testing Alembic for a python project. The autogeneration is really nice, but dropping is not really helpful if you need to work on customer databases with many different versions for example.

Activate or deactivate Dropping for different scenarios. This would be the best solution.

I made my own configuration in env.py, so I can use more than one base script. But if I make a new script (defining a new table) and autogenerate a migration-script I have an autogenerated drop of all previous migrated tables. I looked already for the mako-file. How is it possible to integrate a restriction in the mako-file?


Solution

  • I found a possibility to filter my migration-operations-list. if you hand over a filter-methode who filters your list to the config-flag "process_revision_directives". (all configs in the env.py)

    from alembic.operations import ops
        def process_revision_directives(context, revision, directives):
            script = directives[0]
    
            # process both "def upgrade()", "def downgrade()"
            for directive in (script.upgrade_ops, script.downgrade_ops):
    
                # now rewrite the list of "ops" such that DropColumnOp and DropTableOp
                # are removed for those tables.   Needs a recursive function.
                directive.ops = list(
                    _filter_drop_elm(directive.ops)
                )
    
    
    
        def _filter_drop_elm(directives):
            # given a set of (tablename, schemaname) to be dropped, filter
            # out Drop-Op from the list of directives and yield the result.
            for directive in directives:
                # ModifyTableOps is a container of ALTER TABLE types of
                # commands.  process those in place recursively.
                if isinstance(directive, ops.DropTableOp):
                    continue
                elif isinstance(directive, ops.ModifyTableOps):
    
                    directive.ops = list(
                        _filter_drop_elm(directive.ops)
                    )
                    if not directive.ops:
                        continue
    
                elif isinstance(directive, ops.AlterTableOp) and isinstance(directive, ops.DropColumnOp):
                        continue
    
                # otherwise if not filtered, yield out the directive
                yield directive