Skip to content

Centralize predictions ↔ prediction_review join in a view or helper #649

Description

@jss367

Context

After #636, every read site that wants prediction review state has to repeat the same incantation:

LEFT JOIN prediction_review pr_rev
  ON pr_rev.prediction_id = pr.id AND pr_rev.workspace_id = ?
WHERE COALESCE(pr_rev.status, 'pending') != 'rejected'

#644 is sweeping remaining sites for the related (detector_confidence, labels_fingerprint) filters, but #636 already needed 19 review rounds to find them all, and #644 is at least one more pass. The cost is structural: any future caller that forgets the join + COALESCE will silently surface rejected rows from another workspace.

Fix

Two options:

Option A — SQL view.

CREATE VIEW predictions_for_workspace AS
SELECT pr.*,
       COALESCE(rv.status, 'pending') AS review_status,
       rv.individual, rv.group_id, rv.vote_count, rv.total_votes
FROM predictions pr
LEFT JOIN prediction_review rv
  ON rv.prediction_id = pr.id AND rv.workspace_id = :ws

Tradeoff: SQLite doesn't support parameterized views, so callers still substitute workspace_id — half the win.

Option B — db.predictions_query(ws_id, ...) helper that returns a callable / pre-built Cursor, used everywhere review-aware reads happen. Easier to test and refactor.

Either way, add a regression test that an intentional-bad query (missing the join) fails so the pattern can't drift back.

Sequencing

Best timed after #644 closes, so the sweep happens once and we centralize a single converged shape.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions