From 35690bd1692f067e7ec76898ba2a5ea96adecabe Mon Sep 17 00:00:00 2001 From: cproudlock Date: Mon, 13 Jul 2026 13:06:07 -0400 Subject: [PATCH] Migrations: relax session sql_mode so the chain runs on strict MySQL 8 Found by test-deploying on a Windows + MySQL 8.0 VM: migration 7a01 seeds the canonical relationship types with a raw INSERT that omits the NOT-NULL createddate/modifieddate columns (the ORM supplies those via Python defaults at runtime, but a raw migration INSERT does not). MySQL 5.x's lax default sql_mode accepted it; strict MySQL 8 rejects it with 1364 "Field 'createddate' doesn't have a default value", so a fresh `flask db upgrade` died at 7a01. Dev runs MySQL 5.6, so this never surfaced locally. migrations/env.py now sets the migration session sql_mode to NO_ENGINE_SUBSTITUTION (dropping STRICT_TRANS_TABLES) for the migration run only - the app's own runtime connections keep their mode. Makes the whole chain portable across MySQL versions. Guarded for non-MySQL (sqlite tests). 68 migration/smoke tests pass; fresh upgrade to head verified on MySQL. Co-Authored-By: Claude Opus 4.8 --- migrations/env.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/migrations/env.py b/migrations/env.py index 7d4d697..0c5f7bc 100644 --- a/migrations/env.py +++ b/migrations/env.py @@ -139,6 +139,20 @@ def run_migrations_online(): pass with connectable.connect() as connection: + # Relax the session sql_mode for the migration run. Some historical + # migrations seed reference rows with raw INSERTs that omit NOT-NULL + # timestamp columns (the ORM supplies those via Python defaults at + # runtime, but a raw migration INSERT does not). MySQL 5.x's lax default + # accepted that; strict MySQL 8 rejects it with 1364 "Field 'createddate' + # doesn't have a default value". Dropping STRICT_TRANS_TABLES for the + # migration session only (the app's own connections keep their mode) + # makes the chain portable across MySQL versions. + try: + connection.exec_driver_sql( + "SET SESSION sql_mode = 'NO_ENGINE_SUBSTITUTION'") + except Exception: + pass # non-MySQL backends (e.g. sqlite in tests) + context.configure( connection=connection, target_metadata=get_metadata(),