diff --git a/alembic/env.py b/alembic/env.py index a652b05..0d40d2c 100644 --- a/alembic/env.py +++ b/alembic/env.py @@ -44,10 +44,17 @@ def run_migrations_offline() -> None: def do_run_migrations(connection: Connection) -> None: + # render_as_batch is required for SQLite, which doesn't support + # most ALTER COLUMN / ADD CONSTRAINT operations natively. With + # batch mode enabled, Alembic emits a copy-and-rename dance under + # SQLite while still producing plain ALTER on MariaDB / Postgres, + # so prod migrations are unchanged. Detect via the dialect name. + render_as_batch = connection.dialect.name == "sqlite" context.configure( connection=connection, target_metadata=target_metadata, compare_type=True, + render_as_batch=render_as_batch, ) with context.begin_transaction(): context.run_migrations() diff --git a/alembic/versions/0005_widen_quote_symbol.py b/alembic/versions/0005_widen_quote_symbol.py index 22b2bce..b7f8d33 100644 --- a/alembic/versions/0005_widen_quote_symbol.py +++ b/alembic/versions/0005_widen_quote_symbol.py @@ -17,18 +17,25 @@ depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: - op.alter_column( - "quotes", "symbol", - existing_type=sa.String(64), - type_=sa.String(128), - existing_nullable=False, - ) + # batch_alter_table wraps the ALTER in a copy-and-rename dance for + # SQLite (which doesn't support ALTER COLUMN TYPE) while remaining a + # plain ALTER on MariaDB / Postgres. Required for `alembic upgrade + # head` to work against a fresh SQLite database during local tooling + # or test bootstrap. + with op.batch_alter_table("quotes") as bop: + bop.alter_column( + "symbol", + existing_type=sa.String(64), + type_=sa.String(128), + existing_nullable=False, + ) def downgrade() -> None: - op.alter_column( - "quotes", "symbol", - existing_type=sa.String(128), - type_=sa.String(64), - existing_nullable=False, - ) + with op.batch_alter_table("quotes") as bop: + bop.alter_column( + "symbol", + existing_type=sa.String(128), + type_=sa.String(64), + existing_nullable=False, + ) diff --git a/alembic/versions/0013_referrals.py b/alembic/versions/0013_referrals.py index 6eeae26..89b32f2 100644 --- a/alembic/versions/0013_referrals.py +++ b/alembic/versions/0013_referrals.py @@ -30,23 +30,21 @@ depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: - op.add_column( - "users", - sa.Column("referral_code", sa.String(16), nullable=True), - ) - op.create_unique_constraint( - "uq_users_referral_code", "users", ["referral_code"], - ) - op.add_column( - "users", - sa.Column("referred_by_user_id", sa.Integer, nullable=True), - ) - op.create_foreign_key( - "fk_users_referred_by", - "users", "users", - ["referred_by_user_id"], ["id"], - ondelete="SET NULL", - ) + # batch_alter_table wraps ADD CONSTRAINT in a copy-and-rename for + # SQLite (no native ALTER constraints support); on MariaDB/Postgres + # it falls through to plain ALTER statements. + with op.batch_alter_table("users") as bop: + bop.add_column(sa.Column("referral_code", sa.String(16), nullable=True)) + bop.create_unique_constraint( + "uq_users_referral_code", ["referral_code"], + ) + bop.add_column(sa.Column("referred_by_user_id", sa.Integer, nullable=True)) + bop.create_foreign_key( + "fk_users_referred_by", + "users", + ["referred_by_user_id"], ["id"], + ondelete="SET NULL", + ) op.create_table( "referrals", @@ -71,7 +69,8 @@ def upgrade() -> None: def downgrade() -> None: op.drop_index("ix_referrals_referrer", table_name="referrals") op.drop_table("referrals") - op.drop_constraint("fk_users_referred_by", "users", type_="foreignkey") - op.drop_column("users", "referred_by_user_id") - op.drop_constraint("uq_users_referral_code", "users", type_="unique") - op.drop_column("users", "referral_code") + with op.batch_alter_table("users") as bop: + bop.drop_constraint("fk_users_referred_by", type_="foreignkey") + bop.drop_column("referred_by_user_id") + bop.drop_constraint("uq_users_referral_code", type_="unique") + bop.drop_column("referral_code") diff --git a/alembic/versions/0018_polar_webhook.py b/alembic/versions/0018_polar_webhook.py index bc085a7..5d3f31c 100644 --- a/alembic/versions/0018_polar_webhook.py +++ b/alembic/versions/0018_polar_webhook.py @@ -17,17 +17,12 @@ depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: - op.add_column( - "users", - sa.Column("polar_customer_id", sa.String(length=64), nullable=True), - ) - op.add_column( - "users", - sa.Column("polar_subscription_id", sa.String(length=64), nullable=True), - ) - op.create_unique_constraint( - "uq_users_polar_customer", "users", ["polar_customer_id"], - ) + with op.batch_alter_table("users") as bop: + bop.add_column(sa.Column("polar_customer_id", sa.String(length=64), nullable=True)) + bop.add_column(sa.Column("polar_subscription_id", sa.String(length=64), nullable=True)) + bop.create_unique_constraint( + "uq_users_polar_customer", ["polar_customer_id"], + ) op.create_table( "polar_events", @@ -50,6 +45,7 @@ def upgrade() -> None: def downgrade() -> None: op.drop_index("ix_polar_events_type_received", table_name="polar_events") op.drop_table("polar_events") - op.drop_constraint("uq_users_polar_customer", "users", type_="unique") - op.drop_column("users", "polar_subscription_id") + with op.batch_alter_table("users") as bop: + bop.drop_constraint("uq_users_polar_customer", type_="unique") + bop.drop_column("polar_subscription_id") op.drop_column("users", "polar_customer_id") diff --git a/alembic/versions/0019_stripe.py b/alembic/versions/0019_stripe.py index 3ea4018..acd516d 100644 --- a/alembic/versions/0019_stripe.py +++ b/alembic/versions/0019_stripe.py @@ -18,17 +18,12 @@ depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: - op.add_column( - "users", - sa.Column("stripe_customer_id", sa.String(length=64), nullable=True), - ) - op.add_column( - "users", - sa.Column("stripe_subscription_id", sa.String(length=64), nullable=True), - ) - op.create_unique_constraint( - "uq_users_stripe_customer", "users", ["stripe_customer_id"], - ) + with op.batch_alter_table("users") as bop: + bop.add_column(sa.Column("stripe_customer_id", sa.String(length=64), nullable=True)) + bop.add_column(sa.Column("stripe_subscription_id", sa.String(length=64), nullable=True)) + bop.create_unique_constraint( + "uq_users_stripe_customer", ["stripe_customer_id"], + ) op.create_table( "stripe_events", @@ -51,6 +46,7 @@ def upgrade() -> None: def downgrade() -> None: op.drop_index("ix_stripe_events_type_received", table_name="stripe_events") op.drop_table("stripe_events") - op.drop_constraint("uq_users_stripe_customer", "users", type_="unique") - op.drop_column("users", "stripe_subscription_id") - op.drop_column("users", "stripe_customer_id") + with op.batch_alter_table("users") as bop: + bop.drop_constraint("uq_users_stripe_customer", type_="unique") + bop.drop_column("stripe_subscription_id") + bop.drop_column("stripe_customer_id") diff --git a/alembic/versions/0023_lang_index_and_qd_symbol_widen.py b/alembic/versions/0023_lang_index_and_qd_symbol_widen.py index 42bcb63..31a6eeb 100644 --- a/alembic/versions/0023_lang_index_and_qd_symbol_widen.py +++ b/alembic/versions/0023_lang_index_and_qd_symbol_widen.py @@ -18,21 +18,21 @@ depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: op.create_index("ix_users_lang", "users", ["lang"]) - op.alter_column( - "quotes_daily", - "symbol", - existing_type=sa.String(length=64), - type_=sa.String(length=128), - existing_nullable=False, - ) + with op.batch_alter_table("quotes_daily") as bop: + bop.alter_column( + "symbol", + existing_type=sa.String(length=64), + type_=sa.String(length=128), + existing_nullable=False, + ) def downgrade() -> None: - op.alter_column( - "quotes_daily", - "symbol", - existing_type=sa.String(length=128), - type_=sa.String(length=64), - existing_nullable=False, - ) + with op.batch_alter_table("quotes_daily") as bop: + bop.alter_column( + "symbol", + existing_type=sa.String(length=128), + type_=sa.String(length=64), + existing_nullable=False, + ) op.drop_index("ix_users_lang", table_name="users")