On Sun, Jan 15, 2023, at 6:51 AM, Lele Gaifax wrote:
> Hi all,
> 
> this is loosely related to my other post: modern SA/Alembic transaction
> handling changed (unsurprisingly! :-) somewhat, and old migration trick
> does not work anymore. I found a way out, but maybe there is a better
> approach, who knows!
> 
> My app, being SQLite based, installs an event handler to force SQLite
> FKs check[0]:
> 
>   @event.listens_for(Engine, "connect")
>   def set_sqlite_pragma(dbapi_connection, connection_record):
>       cursor = dbapi_connection.cursor()
>       cursor.execute("PRAGMA foreign_keys=ON")
>       cursor.close()
> 
> As explained in the related Alembic doc[1], I used to disable that check
> in some migrations (for example this[2]), something that surely worked
> when I applied them in production, nearly two years ago.
> 
> Since my last migration something has changed though, and that trick
> doesn't work anymore, apparently because for some reason nowadays
> Alembic issues a BEGIN well before running the migration script and,
> accordingly to SQLite doc[3], that instruction does not work within a
> transaction: a new migration like the following, that change an existing
> column to be NOT NULL

OK, alembic nor sqlalchemy do not emit BEGIN nor they even know how to do this. 
 what will make a sqlite-level BEGIN occur is if some kind of SQL commands are 
running on the connection, like an INSERT or something.    This goes with your 
other email that I dont see what this mystery command is, ahead of the 
migration running.    

you might want to try calling op.get_bind().commit() maybe, or try this feature 
called autocommit_block: 
https://alembic.sqlalchemy.org/en/latest/api/runtime.html#alembic.runtime.migration.MigrationContext.autocommit_block


however, overall, I dont know what's going on here, every migration script 
should be starting with a clean transaction for sqlite assuming 
transaction_per_migration is ON.





> 
>   def upgrade():
>       op.execute("PRAGMA foreign_keys=OFF")
>       op.execute("UPDATE clubs SET nationality='wrl' WHERE nationality IS 
> NULL")
>       with op.batch_alter_table('clubs') as batch:
>           batch.alter_column('nationality',
>                              existing_type=sa.CHAR(length=3),
>                              nullable=False)
> 
> now fails, even running it on a "production equivalent context" that is
> still based on SA 1.3 and Alembic 1.7.6: as soon as it "drops" the old table
> and is going to rename the new temporary table built by
> "batch_alter_table()" the FK check interrupts the process with a
> "sqlite3.IntegrityError: FOREIGN KEY constraint failed" error.
> 
> I found a possible, less-than-ideal workaround moving that PRAGMA
> instruction into the Alembic new, modernized env.py preamble I'm trying
> out while upgrading to SA 2:
> 
>   def run_migrations_online():
>       """Run migrations in 'online' mode.
> 
>       In this scenario we need to create an Engine
>       and associate a connection with the context.
>       """
> 
>       connectable = engine_from_config(
>           config.get_section(config.config_ini_section),
>           prefix="sqlalchemy.",
>           poolclass=pool.NullPool,
>       )
> 
>       with connectable.connect() as connection:
>           # Disable FK validation, turned on by 
> models/__init__.py::set_sqlite_pragma()
>           connection.exec_driver_sql("PRAGMA foreign_keys=OFF")
> 
>           context.configure(
>               connection=connection, target_metadata=target_metadata
>           )
> 
>           with context.begin_transaction():
>               context.run_migrations()
> 
> As this unconditionally affects all migrations, it obviously may ruins
> further ones, where the FK check would be desiderable.
> 
> Can you suggest some better approach?
> 
> Thanks again,
> bye, lele.
> 
> [0] 
> https://gitlab.com/metapensiero/SoL/-/blob/master/src/sol/models/__init__.py#L215
>  
> [1] 
> https://alembic.sqlalchemy.org/en/latest/batch.html#dealing-with-referencing-foreign-keys
> [2] 
> https://gitlab.com/metapensiero/SoL/-/blob/master/alembic/versions/d311277a4da7_widen_urls_size_to_128_characters.py#L17
> [3] https://www.sqlite.org/pragma.html#pragma_foreign_keys
> -- 
> nickname: Lele Gaifax | Quando vivrò di quello che ho pensato ieri
> real: Emanuele Gaifas | comincerò ad aver paura di chi mi copia.
> l...@metapensiero.it  |                 -- Fortunato Depero, 1929.
> 
> -- 
> SQLAlchemy - 
> The Python SQL Toolkit and Object Relational Mapper
> 
> http://www.sqlalchemy.org/
> 
> To post example code, please provide an MCVE: Minimal, Complete, and 
> Verifiable Example.  See  http://stackoverflow.com/help/mcve for a full 
> description.
> --- 
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to sqlalchemy+unsubscr...@googlegroups.com 
> <mailto:sqlalchemy%2bunsubscr...@googlegroups.com>.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/sqlalchemy/87cz7gdnip.fsf%40metapensiero.it.
> 

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sqlalchemy/4c41fa34-51ec-45af-b99c-3fb34f24f0f8%40app.fastmail.com.

Reply via email to