2015-03-16 15 views
20

Próbuję użyć programu alembic do przekonwertowania pola SQLAlchemy PostgreSQL ARRAY (Text) do pola BIT (varying = True) dla jednej z kolumn tabeli.Alembic: zmień typ kolumny za pomocą UŻYWANIA

Kolumna jest obecnie definiowany jako:

cols = Column(ARRAY(TEXT), nullable=False, index=True) 

chcę go zmienić na:

cols = Column(BIT(varying=True), nullable=False, index=True) 

Zmiana typów kolumn nie wydaje się być obsługiwane domyślnie, więc jestem edycji pismo alembikie ręcznie. To jest to, co mam obecnie:

def upgrade(): 
    op.alter_column(
     table_name='views', 
     column_name='cols', 
     nullable=False, 
     type_=postgresql.BIT(varying=True) 
    ) 


def downgrade(): 
    op.alter_column(
     table_name='views', 
     column_name='cols', 
     nullable=False, 
     type_=postgresql.ARRAY(sa.Text()) 
    ) 

jednak działa ten skrypt daje błąd:

Traceback (most recent call last): 
    File "/home/home/.virtualenvs/deus_lex/bin/alembic", line 9, in <module> 
    load_entry_point('alembic==0.7.4', 'console_scripts', 'alembic')() 
    File "/home/home/.virtualenvs/deus_lex/local/lib/python2.7/site-packages/alembic/config.py", line 399, in main 
    CommandLine(prog=prog).main(argv=argv) 
    File "/home/home/.virtualenvs/deus_lex/local/lib/python2.7/site-packages/alembic/config.py", line 393, in main 
    self.run_cmd(cfg, options) 
    File "/home/home/.virtualenvs/deus_lex/local/lib/python2.7/site-packages/alembic/config.py", line 376, in run_cmd 
    **dict((k, getattr(options, k)) for k in kwarg) 
    File "/home/home/.virtualenvs/deus_lex/local/lib/python2.7/site-packages/alembic/command.py", line 165, in upgrade 
    script.run_env() 
    File "/home/home/.virtualenvs/deus_lex/local/lib/python2.7/site-packages/alembic/script.py", line 382, in run_env 
    util.load_python_file(self.dir, 'env.py') 
    File "/home/home/.virtualenvs/deus_lex/local/lib/python2.7/site-packages/alembic/util.py", line 242, in load_python_file 
    module = load_module_py(module_id, path) 
    File "/home/home/.virtualenvs/deus_lex/local/lib/python2.7/site-packages/alembic/compat.py", line 79, in load_module_py 
    mod = imp.load_source(module_id, path, fp) 
    File "./scripts/env.py", line 83, in <module> 
    run_migrations_online() 
    File "./scripts/env.py", line 76, in run_migrations_online 
    context.run_migrations() 
    File "<string>", line 7, in run_migrations 
    File "/home/home/.virtualenvs/deus_lex/local/lib/python2.7/site-packages/alembic/environment.py", line 742, in run_migrations 
    self.get_context().run_migrations(**kw) 
    File "/home/home/.virtualenvs/deus_lex/local/lib/python2.7/site-packages/alembic/migration.py", line 305, in run_migrations 
    step.migration_fn(**kw) 
    File "/home/home/deus_lex/winslow/scripts/versions/2644864bf479_store_caselist_column_views_as_bits.py", line 24, in upgrade 
    type_=postgresql.BIT(varying=True) 
    File "<string>", line 7, in alter_column 
    File "<string>", line 1, in <lambda> 
    File "/home/home/.virtualenvs/deus_lex/local/lib/python2.7/site-packages/alembic/util.py", line 387, in go 
    return fn(*arg, **kw) 
    File "/home/home/.virtualenvs/deus_lex/local/lib/python2.7/site-packages/alembic/operations.py", line 470, in alter_column 
    existing_autoincrement=existing_autoincrement 
    File "/home/home/.virtualenvs/deus_lex/local/lib/python2.7/site-packages/alembic/ddl/impl.py", line 147, in alter_column 
    existing_nullable=existing_nullable, 
    File "/home/home/.virtualenvs/deus_lex/local/lib/python2.7/site-packages/alembic/ddl/impl.py", line 105, in _exec 
    return conn.execute(construct, *multiparams, **params) 
    File "/home/home/.virtualenvs/deus_lex/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 729, in execute 
    return meth(self, multiparams, params) 
    File "/home/home/.virtualenvs/deus_lex/local/lib/python2.7/site-packages/sqlalchemy/sql/ddl.py", line 69, in _execute_on_connection 
    return connection._execute_ddl(self, multiparams, params) 
    File "/home/home/.virtualenvs/deus_lex/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 783, in _execute_ddl 
    compiled 
    File "/home/home/.virtualenvs/deus_lex/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 958, in _execute_context 
    context) 
    File "/home/home/.virtualenvs/deus_lex/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1159, in _handle_dbapi_exception 
    exc_info 
    File "/home/home/.virtualenvs/deus_lex/local/lib/python2.7/site-packages/sqlalchemy/util/compat.py", line 199, in raise_from_cause 
    reraise(type(exception), exception, tb=exc_tb) 
    File "/home/home/.virtualenvs/deus_lex/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 951, in _execute_context 
    context) 
    File "/home/home/.virtualenvs/deus_lex/local/lib/python2.7/site-packages/sqlalchemy/engine/default.py", line 436, in do_execute 
    cursor.execute(statement, parameters) 
sqlalchemy.exc.ProgrammingError: (ProgrammingError) column "cols" cannot be cast automatically to type bit varying 
HINT: Specify a USING expression to perform the conversion. 
'ALTER TABLE views ALTER COLUMN cols TYPE BIT VARYING' {} 

Jak mogę zmienić mój skrypt z wyrażeniu?

Odpowiedz

14

Niestety trzeba użyć surowego SQL, ponieważ alembik nie wypowiada instrukcji USING podczas zmiany typów.

Jednak pisząc niestandardowy SQL do tego jest dość proste:

op.execute('ALTER TABLE views ALTER COLUMN cols TYPE bit varying USING expr') 

Oczywiście trzeba zastąpić expr z wyrazem, który przekształca stary typ danych do nowego typu danych.

21

Od wersji 0.8.8, alembic obsługuje PostgreSQL USING z parametrem postgresql_using:

op.alter_column('views', 'cols', type_=postgresql.BIT(varying=True), postgresql_using='expr') 
+0

+1 za prowadzenie migracje w kodzie, dzięki czemu można łatwo odtworzyć stan bazy danych do innych środowisk. Aby uzyskać więcej wskazówek na temat wyrażenia "USING", celem jest wskazanie postgresowi, jak przesyłać wszystkie aktualnie przechowywane wartości do nowego typu. Na przykład, zmieniając kolumnę całkowitą na varchar, użyjesz czegoś takiego jak 'col_name :: varchar (32)'. –

+0

To było dokładnie to, czego szukałem właśnie teraz. :) –

Powiązane problemy