refactor(db): remove obsolete camera zone column #234
No reviewers
Labels
No labels
blocked
bug
enhancement
high-priority
low-priority
needs-info
needs-triage
ready-for-agent
ready-for-human
referenced
research
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
gabogg/hikcentral!234
Loading…
Reference in a new issue
No description provided.
Delete branch "chore/drop-zone-name-209"
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
Camera INSERTs no longer write the obsolete
zone_namefield, and fresh databases no longer create it. Existing databases drop it at schema startup. Closes #209 and supersedes #220 item 3.Approach
Per the maintainer decision of 2026-10-03 on #209, the migration is one guarded
ALTER TABLE counting_cameras DROP COLUMN zone_name, inline in_run_schemalike the other migrations (app/db/database.py~591-601).PRAGMA table_infostill lists the column.logger.infoline when it drops the column.BEGIN IMMEDIATEnow wraps the whole of_run_schema, so the guard, the DROP and the later migrations commit or roll back together.The
zone_nameregression assertions intests/test_statistics_summary.pyare kept, anddocs/auditis unchanged.Verification
tests/test_camera_schema_migration.pycovers:foreign_key_check;lifespanplus the monitor) ran against a temporary copy of the local validation DB, neverdata/itself:zone_namedropped, 12 of 12 camera rows with matching values,foreign_key_checkreturned[],integrity_checkreturned ok.scripts/check_docs.pyand the full pytest suite pass.Review: pass 1 r38, pass 2 r42 (mergeable). The P3 follow-ups are #261 and #262.
🤖 Generated with Claude Code
WIP: chore(db): remove obsolete camera zone columnto chore(db): remove obsolete camera zone columnFirst code review pass requested for 016a012...f30d4ee, spec #209. Please review the transactional startup rebuild, retained values and schema objects, failure rollback tests, and local database-copy validation evidence. The implementation passed its installed pre-commit checks; the separately requested full-suite run is finishing.
Code review, pass 1 (
origin/master...f30d4ee, spec #209)Result: 1 P2 (maintainer decision below) and 11 P3s. This is pass 1, so fix every finding, merge
origin/master(nowb64e805with #178;git merge-treeshows it merges cleanly and there is no semantic clash) and request a second pass.ce0ff5dDDL, real rows, a trigger,foreign_keys=ON) checked the following:foreign_key_checkreturns[]andintegrity_checkreturns ok.foreign_keysis restored.'General'INSERTs are gone.Spec
P2
ALTER TABLE ... DROP COLUMN(maintainer decision, 2026-10-03).NOT NULLportably, so rebuild the table". A probe shows this is false on SQLite 3.35+, and this machine has 3.51. Python 3.11+ on Windows bundles a new enough SQLite. On the real legacy DDL (with the trailing comment, the appendedresource_group_code REFERENCES ..., a unique index, an incoming CASCADE FK, a view and a trigger),ALTER TABLE counting_cameras DROP COLUMN zone_namekept every row, every dependent row and every schema object.database.py:60matchingzone_name TEXT NOT NULL DEFAULT 'General',exactly. If an install declared the column any other way, it raisesOperationalErrorat :66 on every startup. It also doesn't match any other migration in the file, which all sit inline in_run_schemabehind aPRAGMA table_infoguard.DROP COLUMNin the existing style.sqlite3.sqlite_version < 3.35.logger.infoline when the column is dropped.foreign_key_checkclean. Cut the fixture down to the real legacy DDL plus the variant with the comment, since triggers, views and incoming CASCADE don't exist in production.database.py:41-53), the migration running beforejournal_mode=WALwith its own commit outsideinit_schema, and the CONTEXT.md:57 mismatch.P3
init_dbonly, not an app startup. The spec says "The local validation run (prod DB copy) starts cleanly after the migration", but the evidence only raninit_dbtwice on a copy. Start the app for real (lifespan plus monitor) against a copy of the validation DB, and report rows before and after in the PR.docs/audit/statistics-period-followups-pr-plan.md:10, 25). It now says "the legacy camera zone field" instead of`zone_name`. The spec says "Out of scope: Any other schema cleanup", and the record is history. Revert it.Standards
P3
tests/test_statistics_summary.py:143-150, 418-420). The PR removed the"zone_name" not in entrances[...]and OpenAPInot in entrance_propsassertions. They stop #200 from coming back in the API contract. Keep them.git-and-workflow.md:15reserveschore/for dependencies, CI and tool configs. A schema plus repository change fitsrefactor/. The branch name can stay. Userefactor(db):for new commits and the PR title.f30d4eehas noCo-Authored-Bytrailer.database.py:41-43vs:53). Two processes starting together against an old DB: B ends up raising "Unrecognized retired camera column declaration". Plausible, not probed. Resolved by P2-1 if the guard runs inside the write transaction.chore(db): remove obsolete camera zone columnto refactor(db): remove obsolete camera zone columnPass 1 fixes (
52ecdd8)Merged
origin/master(atb64e805) and resolved all findings from review pass 1 (r38).Per-Finding Resolution Table
DROP COLUMNALTER TABLE counting_cameras DROP COLUMN zone_nameinside_run_schema. Added fail-fast version check (sqlite3.sqlite_version < 3.35raisesRuntimeError) and addedlogger.info("Dropped legacy counting_cameras.zone_name column."). Wrapped schema execution in a write transaction with rollback on failure. Trimmed test fixtures to real legacy DDL and commented variant; retained tests for row preservation, second startup no-op, clean foreign keys, and rollback on injected failure.lifespan(app)and activebackground_monitorfor 2 seconds against an isolated temporary copy (/tmp/val_pr234_.../hikcentral.db) of the main checkout's database created via SQLite backup API in read-only mode. All 12 cameras, 727,028 counting events, 63,876 access cycles, and 87,551 hardware transitions survived intact. Verified clean shutdown, cleanforeign_key_check, andintegrity_check ok.docs/audit/statistics-period-followups-pr-plan.md:10, 25to retain original historical reference to`zone_name`."zone_name" not in entrances[...]and OpenAPI"zone_name" not in entrance_propscontract assertions intests/test_statistics_summary.py.logger.info("Dropped legacy counting_cameras.zone_name column.")usinghikcentral.dbmodule logger upon column drop.CONTEXT.md:57_run_schema()insideinit_schema(), matching the documented schema initialization lifecycle.test_camera_schema_migration.py. Fixture now parameterized across the two real legacy DDL variants (originalce0ff5dand commented).refactor(db)in title and commitsrefactor(db): remove obsolete camera zone columnand usedrefactor(db):for the fix commit.Co-Authored-BytrailerCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>trailer to the commit.BEGIN IMMEDIATE) inside_run_schema(), preventing concurrent startup races.Real Application Startup Evidence (Lifespan + Background Monitor)
Tested against an isolated snapshot copy of
/home/gabogg/Trabajo/Orinokia/hikcentral/data/hikcentral.db(created using SQLite backup API from read-only connection). The application completed full lifespan initialization, started the background monitor, processed startup baseline calculations, ran for 2 seconds, and shut down cleanly.counting_camerascolumns before:['camera_index_code', 'camera_name', 'direction_type', 'zone_name', 'is_active', 'is_excluded', 'today_in', 'today_out', 'last_event_time', 'updated_at']counting_camerascolumns after:['camera_index_code', 'camera_name', 'direction_type', 'is_active', 'is_excluded', 'today_in', 'today_out', 'last_event_time', 'updated_at', 'resource_group_code']PRAGMA foreign_key_check:[]PRAGMA integrity_check:okReady for review pass 2.
Code review, pass 2 (
origin/master...52ecdd8, spec #209 + maintainer decision of 2026-10-03)Result: no P1, no P2 and 7 P3s. Mergeable. Two P3s are filed as #261 and #262. The stale PR description is fixed in place (see below).
ALTER TABLE counting_cameras DROP COLUMN zone_nameinline in_run_schema(database.py:591-601), with a fail-fast check for SQLite older than 3.35 and onelogger.infoline.ce0ff5dDDL (with and without the trailing comment), runninginit_dbtwice:foreign_key_checkreturns[].lifespanplus the monitor, 12 of 12 camera rows,integrity_checkok. The main checkout'sdata/was not touched.Spec
All r38 findings are fixed:
BEGIN IMMEDIATEnow wraps the whole of_run_schema. That is justified by "It runs inside one transaction" and r38 P3-9, and nothing inside it commits partway.P3
REAL_LEGACY_DDLisn't the realce0ff5ddefinition. → #261Standards
r38 standards findings: P3-3 to P3-7 and P3-9 are fixed. P3-8 (missing trailer) is partial.
P3
The SQLite version is checked twice (
database.py:593-596). → #262The try/rollback/raise block is duplicated (
database.py:922-934). → #262FailingConnection.executeoverride has no user. → #261Two commit-history problems, accepted as-is:
f30d4eehas noCo-Authored-Bytrailer and uses thechore(db)type.52ecdd8's body has truncated "..." bullets.PRs merge with a merge commit, so these stay in history. Rewriting the branch for this isn't worth a force-push.
gabogg referenced this pull request2026-10-03 11:34:08 +00:00