Fix migration script: cast SQLite integer booleans to Postgres booleans #82
No reviewers
Labels
No labels
domain:backend
domain:devops
domain:frontend
status:approved
status:in-progress
status:needs-fix
status:qa
type:bug
type:devops
type:feature
No milestone
No project
No assignees
1 participant
Due date
No due date set.
Dependencies
No dependencies set.
Reference
ldraney/pal-e-api!82
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "81-fix-migration-boolean-cast"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
The SQLite-to-Postgres migration script inserts raw integer values (1/0) for boolean columns, causing
DatatypeMismatcherrors. This fix auto-detects boolean columns from the Postgres schema and converts values to Python booleans before insertion.Changes
scripts/migrate_sqlite_to_postgres.py: Addedsqlalchemy.types.Booleanimport. After buildingrow_dicts, inspect the Postgres table schema to find boolean columns, then cast any non-None integer values tobool()before executing the INSERT.Test Plan
DatatypeMismatcherrorsReview Checklist
Related Notes
plan-2026-02-26-tf-modularize-postgres-- Phase 3, Part D (data migration script)Review-fix round 1: Hoisted
inspect(pg_engine)out of thefor table_nameloop to avoid redundant inspector creation on every iteration. No functional change.PR #82 Review
BLOCKERS
None.
NITS
pg_inspectorcreated outside connection context (line 77): The inspector is created frompg_enginebefore thewith pg_engine.connect()block. This works becauseinspect(engine)opens its own transient connection, but it means you have two independent connections to Postgres (the inspector's implicit one and the explicitdst_conn). Not a correctness issue, but you could reuse the inspector already created on line 70 (inspector = inspect(pg_engine)) by hoisting it or renaming. Minor -- no functional impact.No test coverage for the migration script: There are no unit tests exercising the boolean casting logic. Given this is a one-shot migration script and manual verification is planned, this is acceptable, but worth noting.
bool(0)returnsFalse,bool(1)returnsTrue-- butbool(2)returnsTrueas well. If any SQLite integer boolean column somehow has a value other than 0/1, this will silently coerce it. Extremely unlikely for boolean-modeled columns, but worth being aware of.SOP COMPLIANCE
81-fix-migration-boolean-castreferences #81)plan-2026-02-26-tf-modularize-postgres)CODE REVIEW
The fix is clean and correct:
inspect()to dynamically detect boolean columns from the Postgres schema rather than hardcoding column names. This is future-proof -- any new boolean columns added later will be handled automatically.isinstance(c["type"], Boolean)check is the right way to match SQLAlchemy column types from inspector metadata.row_dict[col] is not None) correctly preserves nullable booleans.col in row_dictcheck handles the case where SQLite and Postgres schemas might have different columns (defensive).row_dictsare built but beforedst_conn.execute(insert_sql, row_dicts).The two boolean columns in the current schema are
notes.is_approvedandprojects.is_public, both of which will be correctly detected and cast.VERDICT: APPROVED