Skip to main content

kaizen/store/sqlite/
outcomes.rs

1use super::rows::*;
2use super::*;
3
4impl Store {
5    pub fn upsert_session_outcome(&self, row: &SessionOutcomeRow) -> Result<()> {
6        self.conn.execute(
7            "INSERT INTO session_outcomes (
8                session_id, test_passed, test_failed, test_skipped, build_ok, lint_errors,
9                revert_lines_14d, pr_open, ci_ok, measured_at_ms, measure_error
10            ) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11)
11            ON CONFLICT(session_id) DO UPDATE SET
12                test_passed=excluded.test_passed,
13                test_failed=excluded.test_failed,
14                test_skipped=excluded.test_skipped,
15                build_ok=excluded.build_ok,
16                lint_errors=excluded.lint_errors,
17                revert_lines_14d=excluded.revert_lines_14d,
18                pr_open=excluded.pr_open,
19                ci_ok=excluded.ci_ok,
20                measured_at_ms=excluded.measured_at_ms,
21                measure_error=excluded.measure_error",
22            params![
23                row.session_id,
24                row.test_passed,
25                row.test_failed,
26                row.test_skipped,
27                row.build_ok.map(bool_to_i64),
28                row.lint_errors,
29                row.revert_lines_14d,
30                row.pr_open,
31                row.ci_ok.map(bool_to_i64),
32                row.measured_at_ms as i64,
33                row.measure_error.as_deref(),
34            ],
35        )?;
36        Ok(())
37    }
38
39    pub fn get_session_outcome(&self, session_id: &str) -> Result<Option<SessionOutcomeRow>> {
40        let mut stmt = self.conn.prepare(
41            "SELECT session_id, test_passed, test_failed, test_skipped, build_ok, lint_errors,
42                    revert_lines_14d, pr_open, ci_ok, measured_at_ms, measure_error
43             FROM session_outcomes WHERE session_id = ?1",
44        )?;
45        let row = stmt
46            .query_row(params![session_id], outcome_row)
47            .optional()?;
48        Ok(row)
49    }
50
51    /// Outcomes for sessions in `workspace` whose `started_at` falls in the window.
52    pub fn list_session_outcomes_in_window(
53        &self,
54        workspace: &str,
55        start_ms: u64,
56        end_ms: u64,
57    ) -> Result<Vec<SessionOutcomeRow>> {
58        let mut stmt = self.conn.prepare(
59            "SELECT o.session_id, o.test_passed, o.test_failed, o.test_skipped, o.build_ok, o.lint_errors,
60                    o.revert_lines_14d, o.pr_open, o.ci_ok, o.measured_at_ms, o.measure_error
61             FROM session_outcomes o
62             JOIN sessions s ON s.id = o.session_id
63             WHERE s.workspace = ?1 AND s.started_at_ms >= ?2 AND s.started_at_ms <= ?3
64             ORDER BY o.measured_at_ms ASC",
65        )?;
66        let rows = stmt.query_map(
67            params![workspace, start_ms as i64, end_ms as i64],
68            outcome_row,
69        )?;
70        rows.map(|r| r.map_err(anyhow::Error::from)).collect()
71    }
72}