2008-02-06 18:39:07 +00:00
|
|
|
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
|
|
|
|
|
|
|
|
class TestAddDropColumn(fixture.DB):
|
|
|
|
level=fixture.DB.CONNECT
|
|
|
|
meta = MetaData()
|
|
|
|
# We'll be adding the 'data' column
|
|
|
|
table_name = 'tmp_adddropcol'
|
|
|
|
table_int = 0
|
|
|
|
|
2008-12-02 05:11:36 +00:00
|
|
|
def _setup(self, url):
|
|
|
|
super(TestAddDropColumn, self)._setup(url)
|
2008-02-06 18:39:07 +00:00
|
|
|
self.meta.clear()
|
|
|
|
self.table = Table(self.table_name,self.meta,
|
|
|
|
Column('id',Integer,primary_key=True),
|
|
|
|
)
|
|
|
|
self.meta.bind = self.engine
|
|
|
|
if self.engine.has_table(self.table.name):
|
|
|
|
self.table.drop()
|
|
|
|
self.table.create()
|
2008-12-02 05:11:36 +00:00
|
|
|
|
|
|
|
def _teardown(self):
|
2008-02-06 18:39:07 +00:00
|
|
|
if self.engine.has_table(self.table.name):
|
2008-12-02 01:03:28 +00:00
|
|
|
try:
|
|
|
|
self.table.drop()
|
|
|
|
except:
|
|
|
|
pass
|
2008-02-06 18:39:07 +00:00
|
|
|
self.meta.clear()
|
2008-12-02 05:11:36 +00:00
|
|
|
super(TestAddDropColumn,self)._teardown()
|
2008-02-06 18:39:07 +00:00
|
|
|
|
|
|
|
def run_(self,create_column_func,drop_column_func,*col_p,**col_k):
|
|
|
|
col_name = 'data'
|
|
|
|
|
|
|
|
def _assert_numcols(expected,type_):
|
|
|
|
result = len(self.table.c)
|
2009-01-19 23:39:53 +00:00
|
|
|
|
2008-02-06 18:39:07 +00:00
|
|
|
self.assertEquals(result,expected,
|
|
|
|
"# %s cols incorrect: %s != %s"%(type_,result,expected))
|
|
|
|
if not col_k.get('primary_key',None):
|
|
|
|
return
|
|
|
|
# new primary key: check its length too
|
|
|
|
result = len(self.table.primary_key)
|
|
|
|
self.assertEquals(result,expected,
|
|
|
|
"# %s pks incorrect: %s != %s"%(type_,result,expected))
|
|
|
|
def assert_numcols(expected):
|
|
|
|
# number of cols should be correct in table object and in database
|
|
|
|
# Changed: create/drop shouldn't mess with the objects
|
|
|
|
#_assert_numcols(expected,'object')
|
|
|
|
# Detect # database cols via autoload
|
2009-01-19 23:39:53 +00:00
|
|
|
#self.meta.clear()
|
|
|
|
del self.meta.tables[self.table_name]
|
2008-02-06 18:39:07 +00:00
|
|
|
self.table=Table(self.table_name,self.meta,autoload=True)
|
|
|
|
_assert_numcols(expected,'database')
|
2009-01-19 23:39:53 +00:00
|
|
|
|
2008-02-06 18:39:07 +00:00
|
|
|
assert_numcols(1)
|
|
|
|
if len(col_p) == 0:
|
2008-08-28 01:17:44 +00:00
|
|
|
col_p = [String(40)]
|
2008-02-06 18:39:07 +00:00
|
|
|
col = Column(col_name,*col_p,**col_k)
|
|
|
|
create_column_func(col)
|
|
|
|
#create_column(col,self.table)
|
|
|
|
assert_numcols(2)
|
|
|
|
self.assertEquals(getattr(self.table.c,col_name),col)
|
|
|
|
#drop_column(col,self.table)
|
|
|
|
col = getattr(self.table.c,col_name)
|
|
|
|
drop_column_func(col)
|
|
|
|
assert_numcols(1)
|
|
|
|
|
|
|
|
@fixture.usedb()
|
|
|
|
def test_undefined(self):
|
|
|
|
"""Add/drop columns not yet defined in the table"""
|
|
|
|
def add_func(col):
|
|
|
|
return create_column(col,self.table)
|
|
|
|
def drop_func(col):
|
|
|
|
return drop_column(col,self.table)
|
|
|
|
return self.run_(add_func,drop_func)
|
|
|
|
|
|
|
|
@fixture.usedb()
|
|
|
|
def test_defined(self):
|
|
|
|
"""Add/drop columns already defined in the table"""
|
|
|
|
def add_func(col):
|
|
|
|
self.meta.clear()
|
|
|
|
self.table = Table(self.table_name,self.meta,
|
|
|
|
Column('id',Integer,primary_key=True),
|
|
|
|
col,
|
|
|
|
)
|
|
|
|
return create_column(col,self.table)
|
|
|
|
def drop_func(col):
|
|
|
|
return drop_column(col,self.table)
|
|
|
|
return self.run_(add_func,drop_func)
|
|
|
|
|
|
|
|
@fixture.usedb()
|
|
|
|
def test_method_bound(self):
|
|
|
|
"""Add/drop columns via column methods; columns bound to a table
|
|
|
|
ie. no table parameter passed to function
|
|
|
|
"""
|
|
|
|
def add_func(col):
|
|
|
|
self.assert_(col.table is None,col.table)
|
|
|
|
self.table.append_column(col)
|
|
|
|
return col.create()
|
|
|
|
def drop_func(col):
|
|
|
|
#self.assert_(col.table is None,col.table)
|
|
|
|
#self.table.append_column(col)
|
|
|
|
return col.drop()
|
|
|
|
return self.run_(add_func,drop_func)
|
|
|
|
|
|
|
|
@fixture.usedb()
|
|
|
|
def test_method_notbound(self):
|
|
|
|
"""Add/drop columns via column methods; columns not bound to a table"""
|
|
|
|
def add_func(col):
|
|
|
|
return col.create(self.table)
|
|
|
|
def drop_func(col):
|
|
|
|
return col.drop(self.table)
|
|
|
|
return self.run_(add_func,drop_func)
|
|
|
|
|
|
|
|
@fixture.usedb()
|
|
|
|
def test_tablemethod_obj(self):
|
|
|
|
"""Add/drop columns via table methods; by column object"""
|
|
|
|
def add_func(col):
|
|
|
|
return self.table.create_column(col)
|
|
|
|
def drop_func(col):
|
|
|
|
return self.table.drop_column(col)
|
|
|
|
return self.run_(add_func,drop_func)
|
|
|
|
|
|
|
|
@fixture.usedb()
|
|
|
|
def test_tablemethod_name(self):
|
|
|
|
"""Add/drop columns via table methods; by column name"""
|
|
|
|
def add_func(col):
|
|
|
|
# must be bound to table
|
|
|
|
self.table.append_column(col)
|
|
|
|
return self.table.create_column(col.name)
|
|
|
|
def drop_func(col):
|
|
|
|
# Not necessarily bound to table
|
|
|
|
return self.table.drop_column(col.name)
|
|
|
|
return self.run_(add_func,drop_func)
|
|
|
|
|
|
|
|
@fixture.usedb()
|
|
|
|
def test_byname(self):
|
|
|
|
"""Add/drop columns via functions; by table object and column name"""
|
|
|
|
def add_func(col):
|
|
|
|
self.table.append_column(col)
|
|
|
|
return create_column(col.name,self.table)
|
|
|
|
def drop_func(col):
|
|
|
|
return drop_column(col.name,self.table)
|
|
|
|
return self.run_(add_func,drop_func)
|
|
|
|
|
|
|
|
@fixture.usedb()
|
|
|
|
def test_fk(self):
|
|
|
|
"""Can create columns with foreign keys"""
|
|
|
|
reftable = Table('tmp_ref',self.meta,
|
|
|
|
Column('id',Integer,primary_key=True),
|
|
|
|
)
|
2009-01-10 13:38:44 +00:00
|
|
|
# create FK's target
|
|
|
|
if self.engine.has_table(reftable.name):
|
|
|
|
reftable.drop()
|
|
|
|
reftable.create()
|
2008-02-06 18:39:07 +00:00
|
|
|
def add_func(col):
|
|
|
|
self.table.append_column(col)
|
|
|
|
return create_column(col.name,self.table)
|
|
|
|
def drop_func(col):
|
|
|
|
ret = drop_column(col.name,self.table)
|
|
|
|
if self.engine.has_table(reftable.name):
|
|
|
|
reftable.drop()
|
|
|
|
return ret
|
2009-01-10 13:38:44 +00:00
|
|
|
return self.run_(add_func,drop_func,Integer,
|
|
|
|
ForeignKey(reftable.c.id))
|
2008-02-06 18:39:07 +00:00
|
|
|
|
|
|
|
#@fixture.usedb()
|
|
|
|
#def xtest_pk(self):
|
|
|
|
# """Can create/drop primary key columns
|
|
|
|
# Not supported
|
|
|
|
# """
|
|
|
|
# def add_func(col):
|
|
|
|
# create_column(col,self.table)
|
|
|
|
# def drop_func(col):
|
|
|
|
# drop_column(col,self.table)
|
|
|
|
# # Primary key length is checked in run_
|
|
|
|
# return self.run_(add_func,drop_func,Integer,primary_key=True)
|
|
|
|
|
|
|
|
class TestRename(fixture.DB):
|
|
|
|
level=fixture.DB.CONNECT
|
|
|
|
meta = MetaData()
|
|
|
|
|
2008-12-02 05:11:36 +00:00
|
|
|
def _setup(self, url):
|
|
|
|
super(TestRename, self)._setup(url)
|
2008-02-14 19:10:47 +00:00
|
|
|
self.meta.bind = self.engine #self.meta.connect(self.engine)
|
2008-02-06 18:39:07 +00:00
|
|
|
|
|
|
|
@fixture.usedb()
|
|
|
|
def test_rename_table(self):
|
|
|
|
"""Tables can be renamed"""
|
|
|
|
#self.engine.echo=True
|
|
|
|
name1 = 'name_one'
|
|
|
|
name2 = 'name_two'
|
|
|
|
xname1 = 'x'+name1
|
|
|
|
xname2 = 'x'+name2
|
|
|
|
self.column = Column(name1,Integer)
|
|
|
|
self.meta.clear()
|
|
|
|
self.table = Table(name1,self.meta,self.column)
|
|
|
|
self.index = Index(xname1,self.column,unique=False)
|
|
|
|
if self.engine.has_table(self.table.name):
|
|
|
|
self.table.drop()
|
|
|
|
if self.engine.has_table(name2):
|
|
|
|
tmp = Table(name2,self.meta,autoload=True)
|
|
|
|
tmp.drop()
|
|
|
|
tmp.deregister()
|
|
|
|
del tmp
|
|
|
|
self.table.create()
|
|
|
|
|
|
|
|
def assert_table_name(expected,skip_object_check=False):
|
|
|
|
"""Refresh a table via autoload
|
|
|
|
SA has changed some since this test was written; we now need to do
|
|
|
|
meta.clear() upon reloading a table - clear all rather than a
|
|
|
|
select few. So, this works only if we're working with one table at
|
|
|
|
a time (else, others will vanish too).
|
|
|
|
"""
|
|
|
|
if not skip_object_check:
|
|
|
|
# Table object check
|
|
|
|
self.assertEquals(self.table.name,expected)
|
|
|
|
newname = self.table.name
|
|
|
|
else:
|
|
|
|
# we know the object's name isn't consistent: just assign it
|
|
|
|
newname = expected
|
|
|
|
# Table DB check
|
|
|
|
#table = self.refresh_table(self.table,newname)
|
|
|
|
self.meta.clear()
|
|
|
|
self.table = Table(newname, self.meta, autoload=True)
|
|
|
|
self.assertEquals(self.table.name,expected)
|
|
|
|
def assert_index_name(expected,skip_object_check=False):
|
|
|
|
if not skip_object_check:
|
|
|
|
# Index object check
|
|
|
|
self.assertEquals(self.index.name,expected)
|
|
|
|
else:
|
|
|
|
# object is inconsistent
|
|
|
|
self.index.name = expected
|
|
|
|
# Index DB check
|
|
|
|
#TODO
|
|
|
|
|
|
|
|
try:
|
|
|
|
# Table renames
|
|
|
|
assert_table_name(name1)
|
|
|
|
rename_table(self.table,name2)
|
|
|
|
assert_table_name(name2)
|
|
|
|
self.table.rename(name1)
|
|
|
|
assert_table_name(name1)
|
|
|
|
# ..by just the string
|
|
|
|
rename_table(name1,name2,engine=self.engine)
|
|
|
|
assert_table_name(name2,True) # object not updated
|
|
|
|
|
|
|
|
# Index renames
|
|
|
|
if self.url.startswith('sqlite') or self.url.startswith('mysql'):
|
|
|
|
self.assertRaises(changeset.exceptions.NotSupportedError,
|
|
|
|
self.index.rename,xname2)
|
|
|
|
else:
|
|
|
|
assert_index_name(xname1)
|
|
|
|
rename_index(self.index,xname2,engine=self.engine)
|
|
|
|
assert_index_name(xname2)
|
|
|
|
self.index.rename(xname1)
|
|
|
|
assert_index_name(xname1)
|
|
|
|
# ..by just the string
|
|
|
|
rename_index(xname1,xname2,engine=self.engine)
|
|
|
|
assert_index_name(xname2,True)
|
|
|
|
|
|
|
|
finally:
|
|
|
|
#self.index.drop()
|
|
|
|
if self.table.exists():
|
|
|
|
self.table.drop()
|
|
|
|
|
|
|
|
class TestColumnChange(fixture.DB):
|
|
|
|
level=fixture.DB.CONNECT
|
|
|
|
table_name = 'tmp_colchange'
|
|
|
|
|
2008-12-02 05:11:36 +00:00
|
|
|
def _setup(self, url):
|
|
|
|
super(TestColumnChange, self)._setup(url)
|
2008-02-06 18:39:07 +00:00
|
|
|
self.meta = MetaData(self.engine)
|
|
|
|
self.table = Table(self.table_name,self.meta,
|
|
|
|
Column('id',Integer,primary_key=True),
|
2008-12-02 15:11:26 +00:00
|
|
|
Column('data',String(40),server_default=DefaultClause("tluafed"),nullable=True),
|
2008-02-06 18:39:07 +00:00
|
|
|
)
|
|
|
|
if self.table.exists():
|
|
|
|
self.table.drop()
|
|
|
|
try:
|
|
|
|
self.table.create()
|
|
|
|
except sqlalchemy.exceptions.SQLError,e:
|
|
|
|
# SQLite: database schema has changed
|
|
|
|
if not self.url.startswith('sqlite://'):
|
|
|
|
raise
|
2008-12-02 05:11:36 +00:00
|
|
|
def _teardown(self):
|
2008-04-02 12:39:41 +00:00
|
|
|
if self.table.exists():
|
2008-02-06 18:39:07 +00:00
|
|
|
try:
|
2008-04-02 12:39:41 +00:00
|
|
|
self.table.drop(self.engine)
|
2008-02-06 18:39:07 +00:00
|
|
|
except sqlalchemy.exceptions.SQLError,e:
|
|
|
|
# SQLite: database schema has changed
|
|
|
|
if not self.url.startswith('sqlite://'):
|
|
|
|
raise
|
2008-04-02 12:39:41 +00:00
|
|
|
#self.engine.echo=False
|
2008-12-02 05:11:36 +00:00
|
|
|
super(TestColumnChange, self)._teardown()
|
2008-02-06 18:39:07 +00:00
|
|
|
|
2008-12-30 20:43:40 +00:00
|
|
|
@fixture.usedb()
|
2008-02-06 18:39:07 +00:00
|
|
|
def test_rename(self):
|
|
|
|
"""Can rename a column"""
|
|
|
|
def num_rows(col,content):
|
|
|
|
return len(list(self.table.select(col==content).execute()))
|
|
|
|
# Table content should be preserved in changed columns
|
|
|
|
content = "fgsfds"
|
|
|
|
self.engine.execute(self.table.insert(),data=content,id=42)
|
|
|
|
self.assertEquals(num_rows(self.table.c.data,content),1)
|
|
|
|
|
|
|
|
# ...as a function, given a column object and the new name
|
|
|
|
alter_column(self.table.c.data, name='atad')
|
|
|
|
self.refresh_table(self.table.name)
|
|
|
|
self.assert_('data' not in self.table.c.keys())
|
|
|
|
self.assert_('atad' in self.table.c.keys())
|
|
|
|
#self.assertRaises(AttributeError,getattr,self.table.c,'data')
|
|
|
|
self.table.c.atad # Should not raise exception
|
|
|
|
self.assertEquals(num_rows(self.table.c.atad,content),1)
|
|
|
|
|
|
|
|
# ...as a method, given a new name
|
|
|
|
self.table.c.atad.alter(name='data')
|
|
|
|
self.refresh_table(self.table.name)
|
|
|
|
self.assert_('atad' not in self.table.c.keys())
|
|
|
|
self.table.c.data # Should not raise exception
|
|
|
|
self.assertEquals(num_rows(self.table.c.data,content),1)
|
|
|
|
|
|
|
|
# ...as a function, given a new object
|
2008-08-28 02:11:03 +00:00
|
|
|
col = Column('atad',String(40),server_default=self.table.c.data.server_default)
|
2008-02-06 18:39:07 +00:00
|
|
|
alter_column(self.table.c.data, col)
|
|
|
|
self.refresh_table(self.table.name)
|
|
|
|
self.assert_('data' not in self.table.c.keys())
|
|
|
|
self.table.c.atad # Should not raise exception
|
|
|
|
self.assertEquals(num_rows(self.table.c.atad,content),1)
|
|
|
|
|
|
|
|
# ...as a method, given a new object
|
2008-08-28 02:11:03 +00:00
|
|
|
col = Column('data',String(40),server_default=self.table.c.atad.server_default)
|
2008-02-06 18:39:07 +00:00
|
|
|
self.table.c.atad.alter(col)
|
|
|
|
self.refresh_table(self.table.name)
|
|
|
|
self.assert_('atad' not in self.table.c.keys())
|
|
|
|
self.table.c.data # Should not raise exception
|
|
|
|
self.assertEquals(num_rows(self.table.c.data,content),1)
|
|
|
|
|
2008-12-30 20:43:40 +00:00
|
|
|
@fixture.usedb()
|
2008-02-06 18:39:07 +00:00
|
|
|
def xtest_fk(self):
|
|
|
|
"""Can add/drop foreign key constraints to/from a column
|
|
|
|
Not supported
|
|
|
|
"""
|
|
|
|
self.assert_(self.table.c.data.foreign_key is None)
|
|
|
|
|
|
|
|
# add
|
|
|
|
self.table.c.data.alter(foreign_key=ForeignKey(self.table.c.id))
|
|
|
|
self.refresh_table(self.table.name)
|
|
|
|
self.assert_(self.table.c.data.foreign_key is not None)
|
|
|
|
|
|
|
|
# drop
|
|
|
|
self.table.c.data.alter(foreign_key=None)
|
|
|
|
self.refresh_table(self.table.name)
|
|
|
|
self.assert_(self.table.c.data.foreign_key is None)
|
|
|
|
|
2008-12-30 20:43:40 +00:00
|
|
|
@fixture.usedb()
|
2008-02-06 18:39:07 +00:00
|
|
|
def test_type(self):
|
|
|
|
"""Can change a column's type"""
|
|
|
|
# Entire column definition given
|
|
|
|
self.table.c.data.alter(Column('data',String(42)))
|
|
|
|
self.refresh_table(self.table.name)
|
|
|
|
self.assert_(isinstance(self.table.c.data.type,String))
|
|
|
|
self.assertEquals(self.table.c.data.type.length,42)
|
|
|
|
|
|
|
|
# Just the new type
|
|
|
|
self.table.c.data.alter(type=String(21))
|
|
|
|
self.refresh_table(self.table.name)
|
|
|
|
self.assert_(isinstance(self.table.c.data.type,String))
|
|
|
|
self.assertEquals(self.table.c.data.type.length,21)
|
|
|
|
|
|
|
|
# Different type
|
|
|
|
self.assert_(isinstance(self.table.c.id.type,Integer))
|
|
|
|
self.assertEquals(self.table.c.id.nullable,False)
|
|
|
|
self.table.c.id.alter(type=String(20))
|
|
|
|
self.assertEquals(self.table.c.id.nullable,False)
|
|
|
|
self.refresh_table(self.table.name)
|
|
|
|
self.assert_(isinstance(self.table.c.id.type,String))
|
|
|
|
|
2008-12-30 20:43:40 +00:00
|
|
|
@fixture.usedb(not_supported='mysql')
|
2008-02-06 18:39:07 +00:00
|
|
|
def test_default(self):
|
2008-12-02 15:11:26 +00:00
|
|
|
"""Can change a column's server_default value (DefaultClauses only)
|
|
|
|
Only DefaultClauses are changed here: others are managed by the
|
2008-02-06 18:39:07 +00:00
|
|
|
application / by SA
|
|
|
|
"""
|
|
|
|
#self.engine.echo=True
|
2008-08-28 01:17:44 +00:00
|
|
|
self.assertEquals(self.table.c.data.server_default.arg,'tluafed')
|
2008-02-06 18:39:07 +00:00
|
|
|
|
2008-12-02 15:11:26 +00:00
|
|
|
# Just the new default
|
2008-02-06 18:39:07 +00:00
|
|
|
default = 'my_default'
|
2008-12-02 15:11:26 +00:00
|
|
|
self.table.c.data.alter(server_default=DefaultClause(default))
|
2008-02-06 18:39:07 +00:00
|
|
|
self.refresh_table(self.table.name)
|
2008-08-28 01:17:44 +00:00
|
|
|
#self.assertEquals(self.table.c.data.server_default.arg,default)
|
2008-02-06 18:39:07 +00:00
|
|
|
# TextClause returned by autoload
|
2008-08-28 01:17:44 +00:00
|
|
|
self.assert_(default in str(self.table.c.data.server_default.arg))
|
2008-02-06 18:39:07 +00:00
|
|
|
|
|
|
|
# Column object
|
|
|
|
default = 'your_default'
|
2008-12-02 15:11:26 +00:00
|
|
|
self.table.c.data.alter(Column('data',String(40),server_default=DefaultClause(default)))
|
2008-02-06 18:39:07 +00:00
|
|
|
self.refresh_table(self.table.name)
|
2008-08-28 01:17:44 +00:00
|
|
|
self.assert_(default in str(self.table.c.data.server_default.arg))
|
2008-02-06 18:39:07 +00:00
|
|
|
|
|
|
|
# Remove default
|
2008-08-28 01:17:44 +00:00
|
|
|
self.table.c.data.alter(server_default=None)
|
2008-02-06 18:39:07 +00:00
|
|
|
self.refresh_table(self.table.name)
|
2008-08-28 01:17:44 +00:00
|
|
|
# server_default isn't necessarily None for Oracle
|
|
|
|
#self.assert_(self.table.c.data.server_default is None,self.table.c.data.server_default)
|
2008-02-06 18:39:07 +00:00
|
|
|
self.engine.execute(self.table.insert(),id=11)
|
|
|
|
row = self.table.select().execute().fetchone()
|
|
|
|
self.assert_(row['data'] is None,row['data'])
|
|
|
|
|
|
|
|
|
2008-12-30 20:43:40 +00:00
|
|
|
@fixture.usedb()
|
2008-02-06 18:39:07 +00:00
|
|
|
def test_null(self):
|
|
|
|
"""Can change a column's null constraint"""
|
|
|
|
self.assertEquals(self.table.c.data.nullable,True)
|
|
|
|
|
|
|
|
# Column object
|
|
|
|
self.table.c.data.alter(Column('data',String(40),nullable=False))
|
|
|
|
self.table.nullable=None
|
|
|
|
self.refresh_table(self.table.name)
|
|
|
|
self.assertEquals(self.table.c.data.nullable,False)
|
|
|
|
|
|
|
|
# Just the new status
|
|
|
|
self.table.c.data.alter(nullable=True)
|
|
|
|
self.refresh_table(self.table.name)
|
|
|
|
self.assertEquals(self.table.c.data.nullable,True)
|
|
|
|
|
2008-12-30 20:43:40 +00:00
|
|
|
@fixture.usedb()
|
2008-02-06 18:39:07 +00:00
|
|
|
def xtest_pk(self):
|
|
|
|
"""Can add/drop a column to/from its table's primary key
|
|
|
|
Not supported
|
|
|
|
"""
|
2008-12-30 20:43:40 +00:00
|
|
|
self.engine.echo = True
|
2008-02-06 18:39:07 +00:00
|
|
|
self.assertEquals(len(self.table.primary_key),1)
|
|
|
|
|
|
|
|
# Entire column definition
|
|
|
|
self.table.c.data.alter(Column('data',String,primary_key=True))
|
|
|
|
self.refresh_table(self.table.name)
|
|
|
|
self.assertEquals(len(self.table.primary_key),2)
|
|
|
|
|
|
|
|
# Just the new status
|
|
|
|
self.table.c.data.alter(primary_key=False)
|
|
|
|
self.refresh_table(self.table.name)
|
|
|
|
self.assertEquals(len(self.table.primary_key),1)
|
|
|
|
|
|
|
|
class TestColumnDelta(fixture.Base):
|
|
|
|
def test_deltas(self):
|
|
|
|
def mkcol(name='id',type=String,*p,**k):
|
|
|
|
return Column(name,type,*p,**k)
|
|
|
|
col_orig = mkcol(primary_key=True)
|
|
|
|
|
|
|
|
def verify(expected,original,*p,**k):
|
|
|
|
delta = _ColumnDelta(original,*p,**k)
|
|
|
|
result = delta.keys()
|
|
|
|
result.sort()
|
|
|
|
self.assertEquals(expected,result)
|
|
|
|
return delta
|
|
|
|
|
|
|
|
verify([],col_orig)
|
|
|
|
verify(['name'],col_orig,'ids')
|
|
|
|
# Parameters are always executed, even if they're 'unchanged'
|
|
|
|
# (We can't assume given column is up-to-date)
|
|
|
|
verify(['name','primary_key','type'],col_orig,'id',Integer,primary_key=True)
|
|
|
|
verify(['name','primary_key','type'],col_orig,name='id',type=Integer,primary_key=True)
|
|
|
|
|
|
|
|
# Can compare two columns and find differences
|
|
|
|
col_new = mkcol(name='ids',primary_key=True)
|
|
|
|
verify([],col_orig,col_orig)
|
|
|
|
verify(['name'],col_orig,col_orig,'ids')
|
|
|
|
verify(['name'],col_orig,col_orig,name='ids')
|
|
|
|
verify(['name'],col_orig,col_new)
|
|
|
|
verify(['name','type'],col_orig,col_new,type=String)
|
|
|
|
# Change name, given an up-to-date definition and the current name
|
|
|
|
delta = verify(['name'],col_new,current_name='id')
|
|
|
|
self.assertEquals(delta.get('name'),'ids')
|
|
|
|
# Change other params at the same time
|
|
|
|
verify(['name','type'],col_new,current_name='id',type=String)
|
|
|
|
# Type comparisons
|
|
|
|
verify([],mkcol(type=String),mkcol(type=String))
|
|
|
|
verify(['type'],mkcol(type=String),mkcol(type=Integer))
|
|
|
|
verify(['type'],mkcol(type=String),mkcol(type=String(42)))
|
|
|
|
verify([],mkcol(type=String(42)),mkcol(type=String(42)))
|
|
|
|
verify(['type'],mkcol(type=String(24)),mkcol(type=String(42)))
|
|
|
|
# Other comparisons
|
|
|
|
verify(['primary_key'],mkcol(nullable=False),mkcol(primary_key=True))
|
|
|
|
# PK implies nullable=False
|
|
|
|
verify(['nullable','primary_key'],mkcol(nullable=True),mkcol(primary_key=True))
|
|
|
|
verify([],mkcol(primary_key=True),mkcol(primary_key=True))
|
|
|
|
verify(['nullable'],mkcol(nullable=True),mkcol(nullable=False))
|
|
|
|
verify([],mkcol(nullable=True),mkcol(nullable=True))
|
|
|
|
verify(['default'],mkcol(default=None),mkcol(default='42'))
|
|
|
|
verify([],mkcol(default=None),mkcol(default=None))
|
|
|
|
verify([],mkcol(default='42'),mkcol(default='42'))
|