Skip to content

Schema migration: snapshot_at / performed_at TEXT-affinity #3

@longevityboris

Description

@longevityboris

Backlog item from 2026-04-09 handoff.

Two columns in production DBs have TEXT affinity despite the schema declaring INTEGER:

  • metric_snapshots.snapshot_at (discovered in 2026-04-09 metrics rewrite)
  • engagement_actions.performed_at (discovered 2026-04-09 during hot-targets work — CAST guard added in 5b86c19)

Every new query that touches these columns has to use CAST(col AS INTEGER) both in SELECT and in WHERE/ORDER BY, or it either returns TEXT to rusqlite (which then panics on row.get::<_, i64>) or compares wrong for timestamps crossing the 10→11 digit boundary (year 2286).

Clean fix: one-time schema migration

  1. CREATE TABLE metric_snapshots_v2 (...) with correct INTEGER affinity
  2. INSERT INTO metric_snapshots_v2 SELECT ..., CAST(snapshot_at AS INTEGER), ... FROM metric_snapshots
  3. DROP TABLE metric_snapshots; ALTER TABLE metric_snapshots_v2 RENAME TO metric_snapshots;
  4. Same for engagement_actions or just UPDATE engagement_actions SET performed_at = CAST(performed_at AS INTEGER) (SQLite accepts this even though the declared type lies — affinity is per-cell in SQLite)
  5. Remove the CAST guards from latest_snapshot_full, find_hot_reply_targets, rank_hot_reply_targets

Why it matters: every new query has to remember the CAST. Easy to miss. Ship this during next release cycle.

Reference: handoff §"Gotchas" item 1, code comments in src/intel/store.rs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions