Remove submodule, just put Dependencies in ./libs
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
"""
|
||||
This module contains database dialect specific changeset
|
||||
implementations.
|
||||
"""
|
||||
__all__ = [
|
||||
'postgres',
|
||||
'sqlite',
|
||||
'mysql',
|
||||
'oracle',
|
||||
]
|
||||
@@ -0,0 +1,99 @@
|
||||
"""
|
||||
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
|
||||
|
||||
|
||||
if SQLA_06:
|
||||
FBSchemaGenerator = sa_base.FBDDLCompiler
|
||||
else:
|
||||
FBSchemaGenerator = sa_base.FBSchemaGenerator
|
||||
|
||||
class FBColumnGenerator(FBSchemaGenerator, ansisql.ANSIColumnGenerator):
|
||||
"""Firebird column generator implementation."""
|
||||
|
||||
|
||||
class FBColumnDropper(ansisql.ANSIColumnDropper):
|
||||
"""Firebird column dropper implementation."""
|
||||
|
||||
def visit_column(self, column):
|
||||
"""Firebird supports 'DROP col' instead of 'DROP COLUMN col' syntax
|
||||
|
||||
Drop primary key and unique constraints if dropped column is referencing it."""
|
||||
if column.primary_key:
|
||||
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
|
||||
|
||||
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 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))
|
||||
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()
|
||||
|
||||
|
||||
class FBSchemaChanger(ansisql.ANSISchemaChanger):
|
||||
"""Firebird schema changer implementation."""
|
||||
|
||||
def visit_table(self, table):
|
||||
"""Rename table not supported"""
|
||||
raise exceptions.NotSupportedError(
|
||||
"Firebird does not support renaming tables.")
|
||||
|
||||
def _visit_column_name(self, table, column, delta):
|
||||
self.start_alter_table(table)
|
||||
col_name = self.preparer.quote(delta.current_name, table.quote)
|
||||
new_name = self.preparer.format_column(delta.result_column)
|
||||
self.append('ALTER COLUMN %s TO %s' % (col_name, new_name))
|
||||
|
||||
def _visit_column_nullable(self, table, column, delta):
|
||||
"""Changing NULL is not supported"""
|
||||
# TODO: http://www.firebirdfaq.org/faq103/
|
||||
raise exceptions.NotSupportedError(
|
||||
"Firebird does not support altering NULL bevahior.")
|
||||
|
||||
|
||||
class FBConstraintGenerator(ansisql.ANSIConstraintGenerator):
|
||||
"""Firebird constraint generator implementation."""
|
||||
|
||||
|
||||
class FBConstraintDropper(ansisql.ANSIConstraintDropper):
|
||||
"""Firebird constaint dropper implementation."""
|
||||
|
||||
def cascade_constraint(self, constraint):
|
||||
"""Cascading constraints is not supported"""
|
||||
raise exceptions.NotSupportedError(
|
||||
"Firebird does not support cascading constraints")
|
||||
|
||||
|
||||
class FBDialect(ansisql.ANSIDialect):
|
||||
columngenerator = FBColumnGenerator
|
||||
columndropper = FBColumnDropper
|
||||
schemachanger = FBSchemaChanger
|
||||
constraintgenerator = FBConstraintGenerator
|
||||
constraintdropper = FBConstraintDropper
|
||||
@@ -0,0 +1,94 @@
|
||||
"""
|
||||
MySQL database specific implementations of changeset classes.
|
||||
"""
|
||||
|
||||
from sqlalchemy.databases import mysql as sa_base
|
||||
from sqlalchemy import types as sqltypes
|
||||
|
||||
from migrate import exceptions
|
||||
from migrate.changeset import ansisql, SQLA_06
|
||||
|
||||
|
||||
if not SQLA_06:
|
||||
MySQLSchemaGenerator = sa_base.MySQLSchemaGenerator
|
||||
else:
|
||||
MySQLSchemaGenerator = sa_base.MySQLDDLCompiler
|
||||
|
||||
class MySQLColumnGenerator(MySQLSchemaGenerator, ansisql.ANSIColumnGenerator):
|
||||
pass
|
||||
|
||||
|
||||
class MySQLColumnDropper(ansisql.ANSIColumnDropper):
|
||||
pass
|
||||
|
||||
|
||||
class MySQLSchemaChanger(MySQLSchemaGenerator, ansisql.ANSISchemaChanger):
|
||||
|
||||
def visit_column(self, delta):
|
||||
table = delta.table
|
||||
colspec = self.get_column_specification(delta.result_column)
|
||||
if delta.result_column.autoincrement:
|
||||
primary_keys = [c for c in table.primary_key.columns
|
||||
if (c.autoincrement and
|
||||
isinstance(c.type, sqltypes.Integer) and
|
||||
not c.foreign_keys)]
|
||||
|
||||
if primary_keys:
|
||||
first = primary_keys.pop(0)
|
||||
if first.name == delta.current_name:
|
||||
colspec += " AUTO_INCREMENT"
|
||||
old_col_name = self.preparer.quote(delta.current_name, table.quote)
|
||||
|
||||
self.start_alter_table(table)
|
||||
|
||||
self.append("CHANGE COLUMN %s " % old_col_name)
|
||||
self.append(colspec)
|
||||
self.execute()
|
||||
|
||||
def visit_index(self, param):
|
||||
# If MySQL can do this, I can't find how
|
||||
raise exceptions.NotSupportedError("MySQL cannot rename indexes")
|
||||
|
||||
|
||||
class MySQLConstraintGenerator(ansisql.ANSIConstraintGenerator):
|
||||
pass
|
||||
|
||||
if SQLA_06:
|
||||
class MySQLConstraintDropper(MySQLSchemaGenerator, ansisql.ANSIConstraintDropper):
|
||||
def visit_migrate_check_constraint(self, *p, **k):
|
||||
raise exceptions.NotSupportedError("MySQL does not support CHECK"
|
||||
" constraints, use triggers instead.")
|
||||
|
||||
else:
|
||||
class MySQLConstraintDropper(ansisql.ANSIConstraintDropper):
|
||||
|
||||
def visit_migrate_primary_key_constraint(self, constraint):
|
||||
self.start_alter_table(constraint)
|
||||
self.append("DROP PRIMARY KEY")
|
||||
self.execute()
|
||||
|
||||
def visit_migrate_foreign_key_constraint(self, constraint):
|
||||
self.start_alter_table(constraint)
|
||||
self.append("DROP FOREIGN KEY ")
|
||||
constraint.name = self.get_constraint_name(constraint)
|
||||
self.append(self.preparer.format_constraint(constraint))
|
||||
self.execute()
|
||||
|
||||
def visit_migrate_check_constraint(self, *p, **k):
|
||||
raise exceptions.NotSupportedError("MySQL does not support CHECK"
|
||||
" constraints, use triggers instead.")
|
||||
|
||||
def visit_migrate_unique_constraint(self, constraint, *p, **k):
|
||||
self.start_alter_table(constraint)
|
||||
self.append('DROP INDEX ')
|
||||
constraint.name = self.get_constraint_name(constraint)
|
||||
self.append(self.preparer.format_constraint(constraint))
|
||||
self.execute()
|
||||
|
||||
|
||||
class MySQLDialect(ansisql.ANSIDialect):
|
||||
columngenerator = MySQLColumnGenerator
|
||||
columndropper = MySQLColumnDropper
|
||||
schemachanger = MySQLSchemaChanger
|
||||
constraintgenerator = MySQLConstraintGenerator
|
||||
constraintdropper = MySQLConstraintDropper
|
||||
@@ -0,0 +1,111 @@
|
||||
"""
|
||||
Oracle database specific implementations of changeset classes.
|
||||
"""
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.databases import oracle as sa_base
|
||||
|
||||
from migrate import exceptions
|
||||
from migrate.changeset import ansisql, SQLA_06
|
||||
|
||||
|
||||
if not SQLA_06:
|
||||
OracleSchemaGenerator = sa_base.OracleSchemaGenerator
|
||||
else:
|
||||
OracleSchemaGenerator = sa_base.OracleDDLCompiler
|
||||
|
||||
|
||||
class OracleColumnGenerator(OracleSchemaGenerator, ansisql.ANSIColumnGenerator):
|
||||
pass
|
||||
|
||||
|
||||
class OracleColumnDropper(ansisql.ANSIColumnDropper):
|
||||
pass
|
||||
|
||||
|
||||
class OracleSchemaChanger(OracleSchemaGenerator, ansisql.ANSISchemaChanger):
|
||||
|
||||
def get_column_specification(self, column, **kwargs):
|
||||
# Ignore the NOT NULL generated
|
||||
override_nullable = kwargs.pop('override_nullable', None)
|
||||
if override_nullable:
|
||||
orig = column.nullable
|
||||
column.nullable = True
|
||||
ret = super(OracleSchemaChanger, self).get_column_specification(
|
||||
column, **kwargs)
|
||||
if override_nullable:
|
||||
column.nullable = orig
|
||||
return ret
|
||||
|
||||
def visit_column(self, delta):
|
||||
keys = delta.keys()
|
||||
|
||||
if 'name' in keys:
|
||||
self._run_subvisit(delta,
|
||||
self._visit_column_name,
|
||||
start_alter=False)
|
||||
|
||||
if len(set(('type', 'nullable', 'server_default')).intersection(keys)):
|
||||
self._run_subvisit(delta,
|
||||
self._visit_column_change,
|
||||
start_alter=False)
|
||||
|
||||
def _visit_column_change(self, table, column, delta):
|
||||
# Oracle cannot drop a default once created, but it can set it
|
||||
# to null. We'll do that if default=None
|
||||
# http://forums.oracle.com/forums/message.jspa?messageID=1273234#1273234
|
||||
dropdefault_hack = (column.server_default is None \
|
||||
and 'server_default' in delta.keys())
|
||||
# Oracle apparently doesn't like it when we say "not null" if
|
||||
# the column's already not null. Fudge it, so we don't need a
|
||||
# new function
|
||||
notnull_hack = ((not column.nullable) \
|
||||
and ('nullable' not in delta.keys()))
|
||||
# We need to specify NULL if we're removing a NOT NULL
|
||||
# constraint
|
||||
null_hack = (column.nullable and ('nullable' in delta.keys()))
|
||||
|
||||
if dropdefault_hack:
|
||||
column.server_default = sa.PassiveDefault(sa.sql.null())
|
||||
if notnull_hack:
|
||||
column.nullable = True
|
||||
colspec = self.get_column_specification(column,
|
||||
override_nullable=null_hack)
|
||||
if null_hack:
|
||||
colspec += ' NULL'
|
||||
if notnull_hack:
|
||||
column.nullable = False
|
||||
if dropdefault_hack:
|
||||
column.server_default = None
|
||||
|
||||
self.start_alter_table(table)
|
||||
self.append("MODIFY (")
|
||||
self.append(colspec)
|
||||
self.append(")")
|
||||
|
||||
|
||||
class OracleConstraintCommon(object):
|
||||
|
||||
def get_constraint_name(self, cons):
|
||||
# Oracle constraints can't guess their name like other DBs
|
||||
if not cons.name:
|
||||
raise exceptions.NotSupportedError(
|
||||
"Oracle constraint names must be explicitly stated")
|
||||
return cons.name
|
||||
|
||||
|
||||
class OracleConstraintGenerator(OracleConstraintCommon,
|
||||
ansisql.ANSIConstraintGenerator):
|
||||
pass
|
||||
|
||||
|
||||
class OracleConstraintDropper(OracleConstraintCommon,
|
||||
ansisql.ANSIConstraintDropper):
|
||||
pass
|
||||
|
||||
|
||||
class OracleDialect(ansisql.ANSIDialect):
|
||||
columngenerator = OracleColumnGenerator
|
||||
columndropper = OracleColumnDropper
|
||||
schemachanger = OracleSchemaChanger
|
||||
constraintgenerator = OracleConstraintGenerator
|
||||
constraintdropper = OracleConstraintDropper
|
||||
@@ -0,0 +1,46 @@
|
||||
"""
|
||||
`PostgreSQL`_ database specific implementations of changeset classes.
|
||||
|
||||
.. _`PostgreSQL`: http://www.postgresql.org/
|
||||
"""
|
||||
from migrate.changeset import ansisql, SQLA_06
|
||||
|
||||
if not SQLA_06:
|
||||
from sqlalchemy.databases import postgres as sa_base
|
||||
PGSchemaGenerator = sa_base.PGSchemaGenerator
|
||||
else:
|
||||
from sqlalchemy.databases import postgresql as sa_base
|
||||
PGSchemaGenerator = sa_base.PGDDLCompiler
|
||||
|
||||
|
||||
class PGColumnGenerator(PGSchemaGenerator, ansisql.ANSIColumnGenerator):
|
||||
"""PostgreSQL column generator implementation."""
|
||||
pass
|
||||
|
||||
|
||||
class PGColumnDropper(ansisql.ANSIColumnDropper):
|
||||
"""PostgreSQL column dropper implementation."""
|
||||
pass
|
||||
|
||||
|
||||
class PGSchemaChanger(ansisql.ANSISchemaChanger):
|
||||
"""PostgreSQL schema changer implementation."""
|
||||
pass
|
||||
|
||||
|
||||
class PGConstraintGenerator(ansisql.ANSIConstraintGenerator):
|
||||
"""PostgreSQL constraint generator implementation."""
|
||||
pass
|
||||
|
||||
|
||||
class PGConstraintDropper(ansisql.ANSIConstraintDropper):
|
||||
"""PostgreSQL constaint dropper implementation."""
|
||||
pass
|
||||
|
||||
|
||||
class PGDialect(ansisql.ANSIDialect):
|
||||
columngenerator = PGColumnGenerator
|
||||
columndropper = PGColumnDropper
|
||||
schemachanger = PGSchemaChanger
|
||||
constraintgenerator = PGConstraintGenerator
|
||||
constraintdropper = PGConstraintDropper
|
||||
@@ -0,0 +1,155 @@
|
||||
"""
|
||||
`SQLite`_ database specific implementations of changeset classes.
|
||||
|
||||
.. _`SQLite`: http://www.sqlite.org/
|
||||
"""
|
||||
from UserDict import DictMixin
|
||||
from copy import copy
|
||||
|
||||
from sqlalchemy.databases import sqlite as sa_base
|
||||
|
||||
from migrate import exceptions
|
||||
from migrate.changeset import ansisql, SQLA_06
|
||||
|
||||
|
||||
if not SQLA_06:
|
||||
SQLiteSchemaGenerator = sa_base.SQLiteSchemaGenerator
|
||||
else:
|
||||
SQLiteSchemaGenerator = sa_base.SQLiteDDLCompiler
|
||||
|
||||
class SQLiteCommon(object):
|
||||
|
||||
def _not_supported(self, op):
|
||||
raise exceptions.NotSupportedError("SQLite does not support "
|
||||
"%s; see http://www.sqlite.org/lang_altertable.html" % op)
|
||||
|
||||
|
||||
class SQLiteHelper(SQLiteCommon):
|
||||
|
||||
def recreate_table(self,table,column=None,delta=None):
|
||||
table_name = self.preparer.format_table(table)
|
||||
|
||||
# we remove all indexes so as not to have
|
||||
# problems during copy and re-create
|
||||
for index in table.indexes:
|
||||
index.drop()
|
||||
|
||||
self.append('ALTER TABLE %s RENAME TO migration_tmp' % table_name)
|
||||
self.execute()
|
||||
|
||||
insertion_string = self._modify_table(table, column, delta)
|
||||
|
||||
table.create()
|
||||
self.append(insertion_string % {'table_name': table_name})
|
||||
self.execute()
|
||||
self.append('DROP TABLE migration_tmp')
|
||||
self.execute()
|
||||
|
||||
def visit_column(self, delta):
|
||||
if isinstance(delta, DictMixin):
|
||||
column = delta.result_column
|
||||
table = self._to_table(delta.table)
|
||||
else:
|
||||
column = delta
|
||||
table = self._to_table(column.table)
|
||||
self.recreate_table(table,column,delta)
|
||||
|
||||
class SQLiteColumnGenerator(SQLiteSchemaGenerator,
|
||||
ansisql.ANSIColumnGenerator,
|
||||
# at the end so we get the normal
|
||||
# visit_column by default
|
||||
SQLiteHelper,
|
||||
SQLiteCommon
|
||||
):
|
||||
"""SQLite ColumnGenerator"""
|
||||
|
||||
def _modify_table(self, table, column, delta):
|
||||
columns = ' ,'.join(map(
|
||||
self.preparer.format_column,
|
||||
[c for c in table.columns if c.name!=column.name]))
|
||||
return ('INSERT INTO %%(table_name)s (%(cols)s) '
|
||||
'SELECT %(cols)s from migration_tmp')%{'cols':columns}
|
||||
|
||||
def visit_column(self,column):
|
||||
if column.foreign_keys:
|
||||
SQLiteHelper.visit_column(self,column)
|
||||
else:
|
||||
super(SQLiteColumnGenerator,self).visit_column(column)
|
||||
|
||||
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 here so the table
|
||||
# is re-created properly.
|
||||
column.remove_from_table(column.table,unset_table=False)
|
||||
super(SQLiteColumnDropper,self).visit_column(column)
|
||||
|
||||
|
||||
class SQLiteSchemaChanger(SQLiteHelper, ansisql.ANSISchemaChanger):
|
||||
"""SQLite SchemaChanger"""
|
||||
|
||||
def _modify_table(self, table, column, delta):
|
||||
return 'INSERT INTO %(table_name)s SELECT * from migration_tmp'
|
||||
|
||||
def visit_index(self, index):
|
||||
"""Does not support ALTER INDEX"""
|
||||
self._not_supported('ALTER INDEX')
|
||||
|
||||
|
||||
class SQLiteConstraintGenerator(ansisql.ANSIConstraintGenerator, SQLiteHelper, SQLiteCommon):
|
||||
|
||||
def visit_migrate_primary_key_constraint(self, constraint):
|
||||
tmpl = "CREATE UNIQUE INDEX %s ON %s ( %s )"
|
||||
cols = ', '.join(map(self.preparer.format_column, constraint.columns))
|
||||
tname = self.preparer.format_table(constraint.table)
|
||||
name = self.get_constraint_name(constraint)
|
||||
msg = tmpl % (name, tname, cols)
|
||||
self.append(msg)
|
||||
self.execute()
|
||||
|
||||
def _modify_table(self, table, column, delta):
|
||||
return 'INSERT INTO %(table_name)s SELECT * from migration_tmp'
|
||||
|
||||
def visit_migrate_foreign_key_constraint(self, *p, **k):
|
||||
self.recreate_table(p[0].table)
|
||||
|
||||
def visit_migrate_unique_constraint(self, *p, **k):
|
||||
self.recreate_table(p[0].table)
|
||||
|
||||
|
||||
class SQLiteConstraintDropper(ansisql.ANSIColumnDropper,
|
||||
SQLiteCommon,
|
||||
ansisql.ANSIConstraintCommon):
|
||||
|
||||
def visit_migrate_primary_key_constraint(self, constraint):
|
||||
tmpl = "DROP INDEX %s "
|
||||
name = self.get_constraint_name(constraint)
|
||||
msg = tmpl % (name)
|
||||
self.append(msg)
|
||||
self.execute()
|
||||
|
||||
def visit_migrate_foreign_key_constraint(self, *p, **k):
|
||||
self._not_supported('ALTER TABLE DROP CONSTRAINT')
|
||||
|
||||
def visit_migrate_check_constraint(self, *p, **k):
|
||||
self._not_supported('ALTER TABLE DROP CONSTRAINT')
|
||||
|
||||
def visit_migrate_unique_constraint(self, *p, **k):
|
||||
self._not_supported('ALTER TABLE DROP CONSTRAINT')
|
||||
|
||||
|
||||
# TODO: technically primary key is a NOT NULL + UNIQUE constraint, should add NOT NULL to index
|
||||
|
||||
class SQLiteDialect(ansisql.ANSIDialect):
|
||||
columngenerator = SQLiteColumnGenerator
|
||||
columndropper = SQLiteColumnDropper
|
||||
schemachanger = SQLiteSchemaChanger
|
||||
constraintgenerator = SQLiteConstraintGenerator
|
||||
constraintdropper = SQLiteConstraintDropper
|
||||
@@ -0,0 +1,78 @@
|
||||
"""
|
||||
Module for visitor class mapping.
|
||||
"""
|
||||
import sqlalchemy as sa
|
||||
|
||||
from migrate.changeset import ansisql
|
||||
from migrate.changeset.databases import (sqlite,
|
||||
postgres,
|
||||
mysql,
|
||||
oracle,
|
||||
firebird)
|
||||
|
||||
|
||||
# Map SA dialects to the corresponding Migrate extensions
|
||||
DIALECTS = {
|
||||
"default": ansisql.ANSIDialect,
|
||||
"sqlite": sqlite.SQLiteDialect,
|
||||
"postgres": postgres.PGDialect,
|
||||
"postgresql": postgres.PGDialect,
|
||||
"mysql": mysql.MySQLDialect,
|
||||
"oracle": oracle.OracleDialect,
|
||||
"firebird": firebird.FBDialect,
|
||||
}
|
||||
|
||||
|
||||
def get_engine_visitor(engine, name):
|
||||
"""
|
||||
Get the visitor implementation for the given database engine.
|
||||
|
||||
:param engine: SQLAlchemy Engine
|
||||
:param name: Name of the visitor
|
||||
:type name: string
|
||||
:type engine: Engine
|
||||
:returns: visitor
|
||||
"""
|
||||
# TODO: link to supported visitors
|
||||
return get_dialect_visitor(engine.dialect, name)
|
||||
|
||||
|
||||
def get_dialect_visitor(sa_dialect, name):
|
||||
"""
|
||||
Get the visitor implementation for the given dialect.
|
||||
|
||||
Finds the visitor implementation based on the dialect class and
|
||||
returns and instance initialized with the given name.
|
||||
|
||||
Binds dialect specific preparer to visitor.
|
||||
"""
|
||||
|
||||
# map sa dialect to migrate dialect and return visitor
|
||||
sa_dialect_name = getattr(sa_dialect, 'name', 'default')
|
||||
migrate_dialect_cls = DIALECTS[sa_dialect_name]
|
||||
visitor = getattr(migrate_dialect_cls, name)
|
||||
|
||||
# bind preparer
|
||||
visitor.preparer = sa_dialect.preparer(sa_dialect)
|
||||
|
||||
return visitor
|
||||
|
||||
def run_single_visitor(engine, visitorcallable, element,
|
||||
connection=None, **kwargs):
|
||||
"""Taken from :meth:`sqlalchemy.engine.base.Engine._run_single_visitor`
|
||||
with support for migrate visitors.
|
||||
"""
|
||||
if connection is None:
|
||||
conn = engine.contextual_connect(close_with_result=False)
|
||||
else:
|
||||
conn = connection
|
||||
visitor = visitorcallable(engine.dialect, conn)
|
||||
try:
|
||||
if hasattr(element, '__migrate_visit_name__'):
|
||||
fn = getattr(visitor, 'visit_' + element.__migrate_visit_name__)
|
||||
else:
|
||||
fn = getattr(visitor, 'visit_' + element.__visit_name__)
|
||||
fn(element, **kwargs)
|
||||
finally:
|
||||
if connection is None:
|
||||
conn.close()
|
||||
Reference in New Issue
Block a user