A database migration tool for SQLAlchemy.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Schema modification operations available in migration scripts through the alembic.op module. These operations provide a high-level interface for database schema changes including tables, columns, constraints, indexes, and data manipulation.
from alembic import op
import sqlalchemy as saCreate, drop, and modify database tables.
def create_table(table_name, *columns, if_not_exists=None, **kw):
"""
Create a new table.
Args:
table_name (str): Name of the table to create
*columns: SQLAlchemy Column objects
if_not_exists (bool): Add IF NOT EXISTS clause (v1.16.0+)
**kw: Additional table options (schema, mysql_engine, etc.)
Returns:
Table: SQLAlchemy Table object
"""
def drop_table(table_name, if_exists=None, **kw):
"""
Drop an existing table.
Args:
table_name (str): Name of the table to drop
if_exists (bool): Add IF EXISTS clause (v1.16.0+)
**kw: Additional options (schema, etc.)
Returns:
None
"""
def rename_table(old_table_name, new_table_name, schema=None):
"""
Rename a table.
Args:
old_table_name (str): Current table name
new_table_name (str): New table name
schema (str): Schema name if applicable
Returns:
None
"""Usage Examples:
# Create table with columns
op.create_table('user',
sa.Column('id', sa.Integer, primary_key=True),
sa.Column('name', sa.String(50), nullable=False),
sa.Column('email', sa.String(120), unique=True),
sa.Column('created_at', sa.DateTime, default=sa.func.now())
)
# Drop table
op.drop_table('old_table')
# Rename table
op.rename_table('user', 'users')Add, remove, and modify table columns.
def add_column(table_name, column, if_not_exists=None, **kw):
"""
Add a column to an existing table.
Args:
table_name (str): Name of the table
column (Column): SQLAlchemy Column object to add
if_not_exists (bool): Add IF NOT EXISTS clause (v1.16.0+)
**kw: Additional options (schema, etc.)
"""
def drop_column(table_name, column_name, **kw):
"""
Drop a column from a table.
Args:
table_name (str): Name of the table
column_name (str): Name of the column to drop
**kw: Additional options (schema, etc.)
"""
def alter_column(table_name, column_name, nullable=None, comment=False, server_default=False, new_column_name=None, type_=None, **kw):
"""
Alter properties of an existing column.
Args:
table_name (str): Name of the table
column_name (str): Name of the column to alter
nullable (bool): Change nullable constraint
comment (str|False): Change column comment (False=no change, None=remove)
server_default (str|False): Change server default (False=no change, None=remove)
new_column_name (str): Rename the column
type_ (TypeEngine): Change column type
**kw: Additional options (schema, etc.)
"""Usage Examples:
# Add column
op.add_column('user', sa.Column('phone', sa.String(20)))
# Drop column
op.drop_column('user', 'phone')
# Alter column - change type and nullable
op.alter_column('user', 'email', type_=sa.String(200), nullable=True)
# Rename column
op.alter_column('user', 'name', new_column_name='full_name')
# Change server default
op.alter_column('user', 'created_at', server_default=sa.text('CURRENT_TIMESTAMP'))Create and drop various types of database constraints.
def create_primary_key(constraint_name, table_name, columns, schema=None):
"""
Create a primary key constraint.
Args:
constraint_name (str): Name of the constraint
table_name (str): Name of the table
columns (list): List of column names
schema (str): Schema name if applicable
Returns:
None
"""
def create_foreign_key(constraint_name, source_table, referent_table, local_cols, remote_cols, onupdate=None, ondelete=None, deferrable=None, initially=None, match=None, source_schema=None, referent_schema=None, **dialect_kw):
"""
Create a foreign key constraint.
Args:
constraint_name (str): Name of the constraint
source_table (str): Source table name
referent_table (str): Referenced table name
local_cols (list): Local column names
remote_cols (list): Referenced column names
onupdate (str): ON UPDATE action
ondelete (str): ON DELETE action
deferrable (bool): Whether constraint is deferrable
initially (str): Initial constraint state ('DEFERRED' or 'IMMEDIATE')
match (str): MATCH clause ('FULL', 'PARTIAL', 'SIMPLE')
source_schema (str): Source table schema
referent_schema (str): Referenced table schema
**dialect_kw: Additional dialect-specific options
Returns:
None
"""
def create_check_constraint(constraint_name, table_name, condition, schema=None, **kw):
"""
Create a check constraint.
Args:
constraint_name (str): Name of the constraint
table_name (str): Name of the table
condition (str|ClauseElement): Check condition
schema (str): Schema name if applicable
**kw: Additional options
Returns:
None
"""
def create_unique_constraint(constraint_name, table_name, columns, schema=None, **kw):
"""
Create a unique constraint.
Args:
constraint_name (str): Name of the constraint
table_name (str): Name of the table
columns (list): List of column names
schema (str): Schema name if applicable
**kw: Additional options
Returns:
Any: Constraint object
"""
def create_exclude_constraint(constraint_name, table_name, *elements, where=None, schema=None, deferrable=None, initially=None, using=None, **kw):
"""
Create an exclude constraint (PostgreSQL).
Args:
constraint_name (str): Name of the constraint
table_name (str): Name of the table
*elements: Column/expression and operator pairs
where (str): WHERE clause for partial constraint
schema (str): Schema name if applicable
deferrable (bool): Whether constraint is deferrable
initially (str): Initial constraint checking mode
using (str): Index method to use
**kw: Additional options
Returns:
Optional[Table]: Table object (if created)
"""
def drop_constraint(constraint_name, table_name, type_=None, if_exists=None, schema=None):
"""
Drop a constraint.
Args:
constraint_name (str): Name of the constraint to drop
table_name (str): Name of the table
type_ (str): Constraint type ('foreignkey', 'primary', 'unique', 'check')
if_exists (bool): Add IF EXISTS clause (v1.16.0+)
schema (str): Schema name if applicable
Returns:
None
"""Usage Examples:
# Create primary key
op.create_primary_key('pk_user', 'user', ['id'])
# Create foreign key
op.create_foreign_key('fk_post_user', 'post', 'user', ['user_id'], ['id'], ondelete='CASCADE')
# Create unique constraint
op.create_unique_constraint('uq_user_email', 'user', ['email'])
# Create check constraint
op.create_check_constraint('ck_user_age', 'user', 'age >= 0')
# Drop constraint
op.drop_constraint('fk_old_constraint', 'table_name', type_='foreignkey')Create and drop database indexes for query optimization.
def create_index(index_name, table_name, columns, schema=None, unique=False, if_not_exists=None, **kw):
"""
Create an index.
Args:
index_name (str): Name of the index
table_name (str): Name of the table
columns (list): List of column names or expressions
schema (str): Schema name if applicable
unique (bool): Whether index should be unique
if_not_exists (bool): Add IF NOT EXISTS clause (v1.12.0+)
**kw: Database-specific index options
Returns:
None
"""
def drop_index(index_name, table_name=None, schema=None, if_exists=None, **kw):
"""
Drop an index.
Args:
index_name (str): Name of the index to drop
table_name (str): Name of the table (optional, some databases require)
schema (str): Schema name if applicable
if_exists (bool): Add IF EXISTS clause (v1.12.0+)
**kw: Additional options
Returns:
None
"""Usage Examples:
# Create simple index
op.create_index('ix_user_email', 'user', ['email'])
# Create unique index
op.create_index('ix_user_username', 'user', ['username'], unique=True)
# Create composite index
op.create_index('ix_post_user_date', 'post', ['user_id', 'created_at'])
# Drop index
op.drop_index('ix_old_index', 'user')Execute SQL statements and perform bulk data operations.
def execute(sqltext, execution_options=None):
"""
Execute arbitrary SQL.
Args:
sqltext (str|ClauseElement): SQL statement to execute
execution_options (dict): Execution options
"""
def bulk_insert(table, rows, multiinsert=True):
"""
Perform bulk insert operation.
Args:
table (Table|str): Target table
rows (list): List of dictionaries representing rows
multiinsert (bool): Use multi-row INSERT statements
"""
def inline_literal(value):
"""
Create an inline literal value for SQL generation.
Args:
value: Python value to convert to SQL literal
Returns:
Literal value for inline SQL
"""Usage Examples:
# Execute raw SQL
op.execute("UPDATE user SET status = 'active' WHERE created_at > '2023-01-01'")
# Bulk insert data
user_table = sa.table('user',
sa.column('name'),
sa.column('email')
)
op.bulk_insert(user_table, [
{'name': 'John', 'email': 'john@example.com'},
{'name': 'Jane', 'email': 'jane@example.com'}
])
# Use inline literal
op.execute(f"INSERT INTO config (key, value) VALUES ('version', {op.inline_literal('1.0')})")Special operations for databases with limited ALTER support (particularly SQLite).
def batch_alter_table(table_name, schema=None, recreate='auto', copy_from=None, table_args=(), table_kwargs=None, reflect_args=(), reflect_kwargs=None, naming_convention=None):
"""
Context manager for batch table alterations.
Args:
table_name (str): Name of the table to alter
schema (str): Schema name if applicable
recreate (str): Recreation strategy ('auto', 'always', 'never')
copy_from (Table): Source table to copy from
table_args: Arguments for new table
table_kwargs: Keyword arguments for new table
reflect_args: Arguments for table reflection
reflect_kwargs: Keyword arguments for table reflection
naming_convention (dict): Naming convention for constraints
Returns:
BatchOperations: Context manager for batch operations
"""Usage Examples:
# Batch alter table for SQLite compatibility
with op.batch_alter_table('user') as batch_op:
batch_op.add_column(sa.Column('phone', sa.String(20)))
batch_op.alter_column('email', nullable=True)
batch_op.create_unique_constraint('uq_user_phone', ['phone'])
batch_op.drop_column('old_field')Add and remove table-level comments.
def create_table_comment(table_name, comment, schema=None):
"""
Create a table comment.
Args:
table_name (str): Name of the table
comment (str): Comment text
schema (str): Schema name if applicable
"""
def drop_table_comment(table_name, schema=None):
"""
Drop a table comment.
Args:
table_name (str): Name of the table
schema (str): Schema name if applicable
"""Advanced operation management and customization.
def get_bind():
"""
Get the current database connection.
Returns:
Connection: SQLAlchemy connection object
"""
def get_context():
"""
Get the current migration context.
Returns:
MigrationContext: Current migration context
"""
def f(name):
"""
Mark a name as having a naming convention applied.
Args:
name (str): Name to mark for naming convention processing
Returns:
conv: Naming convention placeholder
"""
def run_async(async_function, *args, **kw_args):
"""
Run an async function in migration context (v1.11+).
Args:
async_function: Async function to execute
*args: Positional arguments
**kw_args: Keyword arguments
Returns:
Any: Function result
"""
def invoke(operation):
"""
Invoke a migration operation programmatically.
Args:
operation: Operation object to invoke
Returns:
Any: Operation result
"""
def implementation_for(op_cls):
"""
Register an implementation for a custom operation class.
Args:
op_cls: Operation class to register implementation for
Returns:
Callable: Decorator function
"""
def register_operation(name, sourcename=None):
"""
Register a new custom operation.
Args:
name (str): Name of the operation
sourcename (str): Source module name
Returns:
Callable: Decorator function
"""
def invoke(operation):
"""
Invoke a migration operation.
Args:
operation (MigrateOperation): Operation to invoke
"""
def f(name):
"""
Create a naming convention reference.
Args:
name (str): Template name
Returns:
str: Formatted name according to naming convention
"""
def implementation_for(op_cls):
"""
Register operation implementation for custom operations.
Args:
op_cls: Operation class to register implementation for
Returns:
Decorator function for implementation registration
"""
def register_operation(name, operation_class):
"""
Register a custom operation.
Args:
name (str): Operation name
operation_class: Custom operation class
"""
def run_async(coro):
"""
Run async operation within migration context.
Args:
coro: Coroutine to execute
Returns:
Result of coroutine execution
"""All operations are executed within a migration context that provides:
postgresql_concurrently=Truemysql_engine='InnoDB'batch_alter_table() for complex changesOperations may raise:
OperationalError: Database-level errorsProgrammingError: SQL syntax or logic errorsIntegrityError: Constraint violationsCommandError: Alembic-specific operation errors# Operation result types
class Table:
name: str
schema: Optional[str]
columns: List[Column]
class BatchOperations:
def add_column(self, column): ...
def drop_column(self, column_name): ...
def alter_column(self, column_name, **kw): ...
def create_index(self, index_name, columns, **kw): ...
def create_unique_constraint(self, constraint_name, columns): ...
def create_foreign_key(self, constraint_name, referent_table, local_cols, remote_cols): ...
def drop_constraint(self, constraint_name): ...Install with Tessl CLI
npx tessl i tessl/pypi-alembic