use sqlalchemy preparer to do SQL quote formatting. this is a raw change, tests are yet to be written
This commit is contained in:
parent
15cb31cea6
commit
8a8b1d2366
@ -31,10 +31,6 @@ class RawAlterTableVisitor(object):
|
||||
ret = ret.fullname
|
||||
return ret
|
||||
|
||||
def _do_quote_table_identifier(self, identifier):
|
||||
"""Returns a quoted version of the given table identifier."""
|
||||
return '"%s"' % identifier
|
||||
|
||||
def start_alter_table(self, param):
|
||||
"""Returns the start of an ``ALTER TABLE`` SQL-Statement.
|
||||
|
||||
@ -47,9 +43,7 @@ class RawAlterTableVisitor(object):
|
||||
or string (table name)
|
||||
"""
|
||||
table = self._to_table(param)
|
||||
table_name = self._to_table_name(table)
|
||||
self.append('\nALTER TABLE %s ' % \
|
||||
self._do_quote_table_identifier(table_name))
|
||||
self.append('\nALTER TABLE %s ' % self.preparer.format_table(table))
|
||||
return table
|
||||
|
||||
def _pk_constraint(self, table, column, status):
|
||||
@ -91,7 +85,7 @@ class ANSIColumnGenerator(AlterTableVisitor, SchemaGenerator):
|
||||
:type column: :class:`sqlalchemy.Column`
|
||||
"""
|
||||
table = self.start_alter_table(column)
|
||||
self.append(" ADD ")
|
||||
self.append("ADD ")
|
||||
colspec = self.get_column_specification(column)
|
||||
self.append(colspec)
|
||||
self.execute()
|
||||
@ -107,7 +101,8 @@ class ANSIColumnGenerator(AlterTableVisitor, SchemaGenerator):
|
||||
|
||||
class ANSIColumnDropper(AlterTableVisitor):
|
||||
"""Extends ANSI SQL dropper for column dropping (``ALTER TABLE
|
||||
DROP COLUMN``)."""
|
||||
DROP COLUMN``).
|
||||
"""
|
||||
|
||||
def visit_column(self, column):
|
||||
"""Drop a column from its table.
|
||||
@ -116,8 +111,7 @@ class ANSIColumnDropper(AlterTableVisitor):
|
||||
:type column: :class:`sqlalchemy.Column`
|
||||
"""
|
||||
table = self.start_alter_table(column)
|
||||
self.append(' DROP COLUMN %s' % \
|
||||
self._do_quote_column_identifier(column.name))
|
||||
self.append(' DROP COLUMN %s' % self.preparer.format_column(column))
|
||||
self.execute()
|
||||
|
||||
|
||||
@ -136,18 +130,11 @@ class ANSISchemaChanger(AlterTableVisitor, SchemaGenerator):
|
||||
name. NONE means the name is unchanged.
|
||||
"""
|
||||
|
||||
def _do_quote_column_identifier(self, identifier):
|
||||
"""override this function to define how identifiers (table and
|
||||
column names) should be written in the SQL. For instance, in
|
||||
PostgreSQL, double quotes should surround the identifier
|
||||
"""
|
||||
return identifier
|
||||
|
||||
def visit_table(self, param):
|
||||
"""Rename a table. Other ops aren't supported."""
|
||||
table, newname = param
|
||||
self.start_alter_table(table)
|
||||
self.append("RENAME TO %s"%newname)
|
||||
self.append("RENAME TO %s" % self.preparer.quote(newname, table.quote))
|
||||
self.execute()
|
||||
|
||||
def visit_column(self, delta):
|
||||
@ -200,8 +187,8 @@ class ANSISchemaChanger(AlterTableVisitor, SchemaGenerator):
|
||||
nullable = delta['nullable']
|
||||
table = self._to_table(delta)
|
||||
self.start_alter_table(table_name)
|
||||
self.append("ALTER COLUMN %s " % \
|
||||
self._do_quote_column_identifier(col_name))
|
||||
# TODO: use preparer.format_column
|
||||
self.append("ALTER COLUMN %s " % self.preparer.quote_identifier(col_name))
|
||||
if nullable:
|
||||
self.append("DROP NOT NULL")
|
||||
else:
|
||||
@ -214,10 +201,11 @@ class ANSISchemaChanger(AlterTableVisitor, SchemaGenerator):
|
||||
dummy = sa.Column(None, None, server_default=server_default)
|
||||
default_text = self.get_column_default_string(dummy)
|
||||
self.start_alter_table(table_name)
|
||||
self.append("ALTER COLUMN %s " % \
|
||||
self._do_quote_column_identifier(col_name))
|
||||
# TODO: use preparer.format_column
|
||||
self.append("ALTER COLUMN %s " % self.preparer.quote_identifier(col_name))
|
||||
if default_text is not None:
|
||||
self.append("SET DEFAULT %s"%default_text)
|
||||
# TODO: format needed?
|
||||
self.append("SET DEFAULT %s" % default_text)
|
||||
else:
|
||||
self.append("DROP DEFAULT")
|
||||
|
||||
@ -229,21 +217,25 @@ class ANSISchemaChanger(AlterTableVisitor, SchemaGenerator):
|
||||
type = type()
|
||||
type_text = type.dialect_impl(self.dialect).get_col_spec()
|
||||
self.start_alter_table(table_name)
|
||||
self.append("ALTER COLUMN %s TYPE %s" % \
|
||||
(self._do_quote_column_identifier(col_name),
|
||||
type_text))
|
||||
# TODO: does type need formating?
|
||||
# TODO: use preparer.format_column
|
||||
self.append("ALTER COLUMN %s TYPE %s" %
|
||||
(self.preparer.quote_identifier(col_name), type_text))
|
||||
|
||||
def _visit_column_name(self, table_name, col_name, delta):
|
||||
new_name = delta['name']
|
||||
self.start_alter_table(table_name)
|
||||
# TODO: use preparer.format_column
|
||||
self.append('RENAME COLUMN %s TO %s' % \
|
||||
(self._do_quote_column_identifier(col_name),
|
||||
self._do_quote_column_identifier(new_name)))
|
||||
(self.preparer.quote_identifier(col_name),
|
||||
self.preparer.quote_identifier(new_name)))
|
||||
|
||||
def visit_index(self, param):
|
||||
"""Rename an index; #36"""
|
||||
index, newname = param
|
||||
self.append("ALTER INDEX %s RENAME TO %s" % (index.name, newname))
|
||||
self.append("ALTER INDEX %s RENAME TO %s" %
|
||||
(self.preparer.quote(self._validate_identifier(index.name, True), index.quote),
|
||||
self.preparer.quote(self._validate_identifier(newname, True) , index.quote)))
|
||||
self.execute()
|
||||
|
||||
|
||||
@ -269,24 +261,24 @@ class ANSIConstraintCommon(AlterTableVisitor):
|
||||
ret = cons.name
|
||||
else:
|
||||
ret = cons.name = cons.autoname()
|
||||
return ret
|
||||
return self.preparer.quote(ret, cons.quote)
|
||||
|
||||
|
||||
class ANSIConstraintGenerator(ANSIConstraintCommon):
|
||||
|
||||
def get_constraint_specification(self, cons, **kwargs):
|
||||
if isinstance(cons, constraint.PrimaryKeyConstraint):
|
||||
col_names = ','.join([i.name for i in cons.columns])
|
||||
col_names = ', '.join([self.preparer.format_column(col) for col in cons.columns])
|
||||
ret = "PRIMARY KEY (%s)" % col_names
|
||||
if cons.name:
|
||||
# Named constraint
|
||||
ret = ("CONSTRAINT %s " % cons.name)+ret
|
||||
ret = ("CONSTRAINT %s " % self.preparer.format_constraint(cons)) + ret
|
||||
elif isinstance(cons, constraint.ForeignKeyConstraint):
|
||||
params = dict(
|
||||
columns=','.join([c.name for c in cons.columns]),
|
||||
reftable=cons.reftable,
|
||||
referenced=','.join([c.name for c in cons.referenced]),
|
||||
name=self.get_constraint_name(cons),
|
||||
columns = ', '.join(map(self.preparer.format_column, cons.columns)),
|
||||
reftable = self.preparer.format_table(cons.reftable),
|
||||
referenced = ', '.join(map(self.preparer.format_column, cons.referenced)),
|
||||
name = self.get_constraint_name(cons),
|
||||
)
|
||||
ret = "CONSTRAINT %(name)s FOREIGN KEY (%(columns)s) "\
|
||||
"REFERENCES %(reftable)s (%(referenced)s)" % params
|
||||
@ -350,7 +342,7 @@ class ANSIFKGenerator(AlterTableVisitor, SchemaGenerator):
|
||||
if self.fk:
|
||||
self.add_foreignkey(self.fk.constraint)
|
||||
|
||||
if self.buffer.getvalue() !='':
|
||||
if self.buffer.getvalue() != '':
|
||||
self.execute()
|
||||
|
||||
def visit_table(self, table):
|
||||
|
@ -10,19 +10,11 @@ MySQLSchemaGenerator = sa_base.MySQLSchemaGenerator
|
||||
|
||||
|
||||
class MySQLColumnGenerator(MySQLSchemaGenerator, ansisql.ANSIColumnGenerator):
|
||||
|
||||
def _do_quote_table_identifier(self, identifier):
|
||||
return '%s'%identifier
|
||||
pass
|
||||
|
||||
|
||||
class MySQLColumnDropper(ansisql.ANSIColumnDropper):
|
||||
|
||||
def _do_quote_table_identifier(self, identifier):
|
||||
return '%s'%identifier
|
||||
|
||||
def _do_quote_column_identifier(self, identifier):
|
||||
return '%s'%identifier
|
||||
pass
|
||||
|
||||
|
||||
class MySQLSchemaChanger(MySQLSchemaGenerator, ansisql.ANSISchemaChanger):
|
||||
@ -49,9 +41,10 @@ class MySQLSchemaChanger(MySQLSchemaGenerator, ansisql.ANSISchemaChanger):
|
||||
if not column.table:
|
||||
column.table = delta.table
|
||||
colspec = self.get_column_specification(column)
|
||||
self.start_alter_table(table_name)
|
||||
# TODO: we need table formating here
|
||||
self.start_alter_table(self.preparer.quote(table_name, True))
|
||||
self.append("CHANGE COLUMN ")
|
||||
self.append(col_name)
|
||||
self.append(self.preparer.quote(col_name, True))
|
||||
self.append(' ')
|
||||
self.append(colspec)
|
||||
|
||||
@ -59,14 +52,9 @@ class MySQLSchemaChanger(MySQLSchemaGenerator, ansisql.ANSISchemaChanger):
|
||||
# If MySQL can do this, I can't find how
|
||||
raise exceptions.NotSupportedError("MySQL cannot rename indexes")
|
||||
|
||||
def _do_quote_table_identifier(self, identifier):
|
||||
return '%s'%identifier
|
||||
|
||||
|
||||
class MySQLConstraintGenerator(ansisql.ANSIConstraintGenerator):
|
||||
|
||||
def _do_quote_table_identifier(self, identifier):
|
||||
return '%s'%identifier
|
||||
pass
|
||||
|
||||
|
||||
class MySQLConstraintDropper(ansisql.ANSIConstraintDropper):
|
||||
@ -85,12 +73,9 @@ class MySQLConstraintDropper(ansisql.ANSIConstraintDropper):
|
||||
def visit_migrate_foreign_key_constraint(self, constraint):
|
||||
self.start_alter_table(constraint)
|
||||
self.append("DROP FOREIGN KEY ")
|
||||
self.append(constraint.name)
|
||||
self.append(self.preparer.format_constraint(constraint))
|
||||
self.execute()
|
||||
|
||||
def _do_quote_table_identifier(self, identifier):
|
||||
return '%s'%identifier
|
||||
|
||||
|
||||
class MySQLDialect(ansisql.ANSIDialect):
|
||||
columngenerator = MySQLColumnGenerator
|
||||
|
@ -67,8 +67,8 @@ class OracleSchemaChanger(OracleSchemaGenerator, ansisql.ANSISchemaChanger):
|
||||
column.server_default = sa.PassiveDefault(sa.sql.null())
|
||||
if notnull_hack:
|
||||
column.nullable = True
|
||||
colspec=self.get_column_specification(column,
|
||||
override_nullable=null_hack)
|
||||
colspec = self.get_column_specification(column,
|
||||
override_nullable=null_hack)
|
||||
if null_hack:
|
||||
colspec += ' NULL'
|
||||
if notnull_hack:
|
||||
@ -76,7 +76,8 @@ class OracleSchemaChanger(OracleSchemaGenerator, ansisql.ANSISchemaChanger):
|
||||
if dropdefault_hack:
|
||||
column.server_default = None
|
||||
|
||||
self.start_alter_table(table_name)
|
||||
# TODO: format from table
|
||||
self.start_alter_table(self.preparer.quote(table_name, True))
|
||||
self.append("MODIFY ")
|
||||
self.append(colspec)
|
||||
|
||||
|
@ -11,40 +11,27 @@ from sqlalchemy.databases import postgres as sa_base
|
||||
PGSchemaGenerator = sa_base.PGSchemaGenerator
|
||||
|
||||
|
||||
class PGSchemaGeneratorMixin(object):
|
||||
"""Common code used by the PostgreSQL specific classes."""
|
||||
|
||||
def _do_quote_table_identifier(self, identifier):
|
||||
return identifier
|
||||
|
||||
def _do_quote_column_identifier(self, identifier):
|
||||
return '"%s"'%identifier
|
||||
|
||||
|
||||
class PGColumnGenerator(PGSchemaGenerator, ansisql.ANSIColumnGenerator,
|
||||
PGSchemaGeneratorMixin):
|
||||
class PGColumnGenerator(PGSchemaGenerator, ansisql.ANSIColumnGenerator):
|
||||
"""PostgreSQL column generator implementation."""
|
||||
pass
|
||||
|
||||
|
||||
class PGColumnDropper(ansisql.ANSIColumnDropper, PGSchemaGeneratorMixin):
|
||||
class PGColumnDropper(ansisql.ANSIColumnDropper):
|
||||
"""PostgreSQL column dropper implementation."""
|
||||
pass
|
||||
|
||||
|
||||
class PGSchemaChanger(ansisql.ANSISchemaChanger, PGSchemaGeneratorMixin):
|
||||
class PGSchemaChanger(ansisql.ANSISchemaChanger):
|
||||
"""PostgreSQL schema changer implementation."""
|
||||
pass
|
||||
|
||||
|
||||
class PGConstraintGenerator(ansisql.ANSIConstraintGenerator,
|
||||
PGSchemaGeneratorMixin):
|
||||
class PGConstraintGenerator(ansisql.ANSIConstraintGenerator):
|
||||
"""PostgreSQL constraint generator implementation."""
|
||||
pass
|
||||
|
||||
|
||||
class PGConstraintDropper(ansisql.ANSIConstraintDropper,
|
||||
PGSchemaGeneratorMixin):
|
||||
class PGConstraintDropper(ansisql.ANSIConstraintDropper):
|
||||
"""PostgreSQL constaint dropper implementation."""
|
||||
pass
|
||||
|
||||
|
@ -19,7 +19,7 @@ class SQLiteHelper(object):
|
||||
except:
|
||||
table = self._to_table(param)
|
||||
raise
|
||||
table_name = self._to_table_name(table)
|
||||
table_name = self.preparer.format_table(table)
|
||||
self.append('ALTER TABLE %s RENAME TO migration_tmp' % table_name)
|
||||
self.execute()
|
||||
|
||||
@ -41,7 +41,7 @@ class SQLiteColumnDropper(SQLiteHelper, ansisql.ANSIColumnDropper):
|
||||
|
||||
def _modify_table(self, table, column):
|
||||
del table.columns[column.name]
|
||||
columns = ','.join([c.name for c in table.columns])
|
||||
columns = ' ,'.join(map(self.preparer.format_column, table.columns))
|
||||
return 'INSERT INTO %(table_name)s SELECT ' + columns + \
|
||||
' from migration_tmp'
|
||||
|
||||
@ -50,7 +50,7 @@ class SQLiteSchemaChanger(SQLiteHelper, ansisql.ANSISchemaChanger):
|
||||
|
||||
def _not_supported(self, op):
|
||||
raise exceptions.NotSupportedError("SQLite does not support "
|
||||
"%s; see http://www.sqlite.org/lang_altertable.html"%op)
|
||||
"%s; see http://www.sqlite.org/lang_altertable.html" % op)
|
||||
|
||||
def _modify_table(self, table, delta):
|
||||
column = table.columns[delta.current_name]
|
||||
@ -61,17 +61,14 @@ class SQLiteSchemaChanger(SQLiteHelper, ansisql.ANSISchemaChanger):
|
||||
def visit_index(self, param):
|
||||
self._not_supported('ALTER INDEX')
|
||||
|
||||
def _do_quote_column_identifier(self, identifier):
|
||||
return '"%s"'%identifier
|
||||
|
||||
|
||||
class SQLiteConstraintGenerator(ansisql.ANSIConstraintGenerator):
|
||||
|
||||
def visit_migrate_primary_key_constraint(self, constraint):
|
||||
tmpl = "CREATE UNIQUE INDEX %s ON %s ( %s )"
|
||||
cols = ','.join([c.name for c in constraint.columns])
|
||||
tname = constraint.table.name
|
||||
name = constraint.name
|
||||
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()
|
||||
@ -84,15 +81,15 @@ class SQLiteFKGenerator(SQLiteSchemaChanger, ansisql.ANSIFKGenerator):
|
||||
if self.fk:
|
||||
self._not_supported("ALTER TABLE ADD FOREIGN KEY")
|
||||
|
||||
if self.buffer.getvalue() !='':
|
||||
if self.buffer.getvalue() != '':
|
||||
self.execute()
|
||||
|
||||
|
||||
class SQLiteConstraintDropper(ansisql.ANSIColumnDropper):
|
||||
class SQLiteConstraintDropper(ansisql.ANSIColumnDropper, ansisql.ANSIConstraintCommon):
|
||||
|
||||
def visit_migrate_primary_key_constraint(self, constraint):
|
||||
tmpl = "DROP INDEX %s "
|
||||
name = constraint.name
|
||||
name = self.get_constraint_name(constraint)
|
||||
msg = tmpl % (name)
|
||||
self.append(msg)
|
||||
self.execute()
|
||||
|
@ -18,7 +18,14 @@ dialects = {
|
||||
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)
|
||||
|
||||
|
||||
@ -28,7 +35,16 @@ def get_dialect_visitor(sa_dialect, name):
|
||||
|
||||
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_cls = sa_dialect.__class__
|
||||
migrate_dialect_cls = dialects[sa_dialect_cls]
|
||||
return migrate_dialect_cls.visitor(name)
|
||||
visitor = migrate_dialect_cls.visitor(name)
|
||||
|
||||
# bind preparer
|
||||
visitor.preparer = sa_dialect.preparer(sa_dialect)
|
||||
|
||||
return visitor
|
||||
|
@ -7,18 +7,15 @@ class Error(Exception):
|
||||
"""
|
||||
Changeset error.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class NotSupportedError(Error):
|
||||
"""
|
||||
Not supported error.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class InvalidConstraintError(Error):
|
||||
"""
|
||||
Invalid constraint error.
|
||||
"""
|
||||
pass
|
||||
|
@ -8,23 +8,29 @@ import sqlalchemy
|
||||
from migrate.changeset.databases.visitor import get_engine_visitor
|
||||
|
||||
__all__ = [
|
||||
'create_column',
|
||||
'drop_column',
|
||||
'alter_column',
|
||||
'rename_table',
|
||||
'rename_index',
|
||||
'create_column',
|
||||
'drop_column',
|
||||
'alter_column',
|
||||
'rename_table',
|
||||
'rename_index',
|
||||
]
|
||||
|
||||
|
||||
def create_column(column, table=None, *p, **k):
|
||||
"""Create a column, given the table"""
|
||||
"""Create a column, given the table
|
||||
|
||||
API to :meth:`column.create`
|
||||
"""
|
||||
if table is not None:
|
||||
return table.create_column(column, *p, **k)
|
||||
return column.create(*p, **k)
|
||||
|
||||
|
||||
def drop_column(column, table=None, *p, **k):
|
||||
"""Drop a column, given the table"""
|
||||
"""Drop a column, given the table
|
||||
|
||||
API to :meth:`column.drop`
|
||||
"""
|
||||
if table is not None:
|
||||
return table.drop_column(column, *p, **k)
|
||||
return column.drop(*p, **k)
|
||||
@ -32,7 +38,10 @@ def drop_column(column, table=None, *p, **k):
|
||||
|
||||
def rename_table(table, name, engine=None):
|
||||
"""Rename a table, given the table's current name and the new
|
||||
name."""
|
||||
name.
|
||||
|
||||
API to :meth:`table.rename`
|
||||
"""
|
||||
table = _to_table(table, engine)
|
||||
table.rename(name)
|
||||
|
||||
@ -43,6 +52,8 @@ def rename_index(index, name, table=None, engine=None):
|
||||
Takes an index name/object, a table name/object, and an
|
||||
engine. Engine and table aren't required if an index object is
|
||||
given.
|
||||
|
||||
API to :meth:`index.rename`
|
||||
"""
|
||||
index = _to_index(index, table, engine)
|
||||
index.rename(name)
|
||||
@ -52,6 +63,8 @@ def alter_column(*p, **k):
|
||||
|
||||
Parameters: column name, table name, an engine, and the properties
|
||||
of that column to change
|
||||
|
||||
API to :meth:`column.alter`
|
||||
"""
|
||||
if len(p) and isinstance(p[0], sqlalchemy.Column):
|
||||
col = p[0]
|
||||
@ -170,6 +183,7 @@ class _ColumnDelta(dict):
|
||||
# Things are initialized differently depending on how many column
|
||||
# parameters are given. Figure out how many and call the appropriate
|
||||
# method.
|
||||
|
||||
if len(p) >= 1 and isinstance(p[0], sqlalchemy.Column):
|
||||
# At least one column specified
|
||||
if len(p) >= 2 and isinstance(p[1], sqlalchemy.Column):
|
||||
@ -183,25 +197,28 @@ class _ColumnDelta(dict):
|
||||
func = self._init_0col
|
||||
diffs = func(*p, **k)
|
||||
self._set_diffs(diffs)
|
||||
# Column attributes that can be altered
|
||||
diff_keys = ('name', 'type', 'nullable', 'default', 'server_default',
|
||||
'primary_key', 'foreign_key')
|
||||
|
||||
def _get_table_name(self):
|
||||
# Column attributes that can be altered
|
||||
diff_keys = ('name',
|
||||
'type',
|
||||
'nullable',
|
||||
'default',
|
||||
'server_default',
|
||||
'primary_key',
|
||||
'foreign_key')
|
||||
|
||||
@property
|
||||
def table_name(self):
|
||||
if isinstance(self._table, basestring):
|
||||
ret = self._table
|
||||
else:
|
||||
ret = self._table.name
|
||||
return ret
|
||||
table_name = property(_get_table_name)
|
||||
|
||||
def _get_table(self):
|
||||
if isinstance(self._table, basestring):
|
||||
ret = None
|
||||
else:
|
||||
ret = self._table
|
||||
return ret
|
||||
table = property(_get_table)
|
||||
@property
|
||||
def table(self):
|
||||
if isinstance(self._table, sqlalchemy.Table):
|
||||
return self._table
|
||||
|
||||
def _init_0col(self, current_name, *p, **k):
|
||||
p, k = self._init_normalize_params(p, k)
|
||||
@ -324,7 +341,7 @@ class ChangesetTable(object):
|
||||
"""Fullname should always be up to date"""
|
||||
# Copied from Table constructor
|
||||
if self.schema is not None:
|
||||
ret = "%s.%s"%(self.schema, self.name)
|
||||
ret = "%s.%s" % (self.schema, self.name)
|
||||
else:
|
||||
ret = self.name
|
||||
return ret
|
||||
|
@ -1,15 +1,22 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sqlalchemy
|
||||
from sqlalchemy import *
|
||||
from test import fixture
|
||||
from migrate import changeset
|
||||
from migrate.changeset import *
|
||||
from migrate.changeset.schema import _ColumnDelta
|
||||
from sqlalchemy.databases import information_schema
|
||||
|
||||
import migrate
|
||||
from migrate import changeset
|
||||
from migrate.changeset import *
|
||||
from migrate.changeset.schema import _ColumnDelta
|
||||
|
||||
from test import fixture
|
||||
|
||||
|
||||
# TODO: add sqlite unique constraints (indexes), test quoting
|
||||
|
||||
class TestAddDropColumn(fixture.DB):
|
||||
level=fixture.DB.CONNECT
|
||||
level = fixture.DB.CONNECT
|
||||
meta = MetaData()
|
||||
# We'll be adding the 'data' column
|
||||
table_name = 'tmp_adddropcol'
|
||||
|
@ -1,34 +1,40 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from sqlalchemy import *
|
||||
from sqlalchemy.util import *
|
||||
from test import fixture
|
||||
|
||||
from migrate.changeset import *
|
||||
|
||||
from test import fixture
|
||||
|
||||
class TestConstraint(fixture.DB):
|
||||
level=fixture.DB.CONNECT
|
||||
level = fixture.DB.CONNECT
|
||||
|
||||
def _setup(self, url):
|
||||
super(TestConstraint, self)._setup(url)
|
||||
self._create_table()
|
||||
|
||||
def _teardown(self):
|
||||
if hasattr(self,'table') and self.engine.has_table(self.table.name):
|
||||
if hasattr(self, 'table') and self.engine.has_table(self.table.name):
|
||||
self.table.drop()
|
||||
super(TestConstraint, self)._teardown()
|
||||
|
||||
def _create_table(self):
|
||||
self._connect(self.url)
|
||||
self.meta = MetaData(self.engine)
|
||||
self.table = Table('mytable',self.meta,
|
||||
Column('id',Integer),
|
||||
Column('fkey',Integer),
|
||||
mysql_engine='InnoDB'
|
||||
)
|
||||
self.table = Table('mytable', self.meta,
|
||||
Column('id', Integer),
|
||||
Column('fkey', Integer),
|
||||
mysql_engine='InnoDB')
|
||||
if self.engine.has_table(self.table.name):
|
||||
self.table.drop()
|
||||
self.table.create()
|
||||
#self.assertEquals(self.table.primary_key,[])
|
||||
self.assertEquals(len(self.table.primary_key),0)
|
||||
self.assertEquals(len(self.table.primary_key), 0)
|
||||
self.assert_(isinstance(self.table.primary_key,
|
||||
schema.PrimaryKeyConstraint),self.table.primary_key.__class__)
|
||||
def _define_pk(self,*cols):
|
||||
schema.PrimaryKeyConstraint), self.table.primary_key.__class__)
|
||||
|
||||
def _define_pk(self, *cols):
|
||||
# Add a pk by creating a PK constraint
|
||||
pk = PrimaryKeyConstraint(table=self.table, *cols)
|
||||
self.assertEquals(list(pk.columns),list(cols))
|
||||
@ -38,7 +44,7 @@ class TestConstraint(fixture.DB):
|
||||
pk.create()
|
||||
self.refresh_table()
|
||||
if not self.url.startswith('sqlite'):
|
||||
self.assertEquals(list(self.table.primary_key),list(cols))
|
||||
self.assertEquals(list(self.table.primary_key), list(cols))
|
||||
#self.assert_(self.table.primary_key.name is not None)
|
||||
|
||||
# Drop the PK constraint
|
||||
@ -99,19 +105,19 @@ class TestConstraint(fixture.DB):
|
||||
def test_define_pk_multi(self):
|
||||
"""Multicolumn PK constraints can be defined, created, and dropped"""
|
||||
#self.engine.echo=True
|
||||
self._define_pk(self.table.c.id,self.table.c.fkey)
|
||||
self._define_pk(self.table.c.id, self.table.c.fkey)
|
||||
|
||||
|
||||
class TestAutoname(fixture.DB):
|
||||
level=fixture.DB.CONNECT
|
||||
level = fixture.DB.CONNECT
|
||||
|
||||
def _setup(self, url):
|
||||
super(TestAutoname, self)._setup(url)
|
||||
self._connect(self.url)
|
||||
self.meta = MetaData(self.engine)
|
||||
self.table = Table('mytable',self.meta,
|
||||
Column('id',Integer),
|
||||
Column('fkey',String(40)),
|
||||
Column('id', Integer),
|
||||
Column('fkey', String(40)),
|
||||
)
|
||||
if self.engine.has_table(self.table.name):
|
||||
self.table.drop()
|
||||
@ -129,6 +135,7 @@ class TestAutoname(fixture.DB):
|
||||
cons = PrimaryKeyConstraint(self.table.c.id)
|
||||
cons.create()
|
||||
self.refresh_table()
|
||||
# TODO: test for index for sqlite
|
||||
if not self.url.startswith('sqlite'):
|
||||
self.assertEquals(list(cons.columns),list(self.table.primary_key))
|
||||
|
||||
@ -136,4 +143,4 @@ class TestAutoname(fixture.DB):
|
||||
cons.name = None
|
||||
cons.drop()
|
||||
self.refresh_table()
|
||||
self.assertEquals(list(),list(self.table.primary_key))
|
||||
self.assertEquals(list(), list(self.table.primary_key))
|
||||
|
Loading…
x
Reference in New Issue
Block a user