| 1 | //! Database connection and schema setup via Toasty. |
| 2 | |
| 3 | use std::path::Path; |
| 4 | |
| 5 | use crate::error::Result; |
| 6 | use crate::models::{CiRun, Repository, Session, SshKey, User}; |
| 7 | |
| 8 | /// Open (creating if necessary) the SQLite database at `path`, creating the |
| 9 | /// schema on first run. |
| 10 | /// |
| 11 | /// Note: Toasty 0.7's `push_schema` emits plain `CREATE TABLE` (no |
| 12 | /// `IF NOT EXISTS`) for model tables, so it is *not* idempotent — calling it on |
| 13 | /// an existing database errors. We therefore only push the schema when the |
| 14 | /// database file does not yet exist. Skipping it on an existing database issues |
| 15 | /// no DDL, so data is never touched. Schema evolution will move to Toasty's |
| 16 | /// migration system when models start changing. |
| 17 | pub async fn connect(path: impl AsRef<Path>) -> Result<toasty::Db> { |
| 18 | let path = path.as_ref(); |
| 19 | let fresh = !path.exists(); |
| 20 | let url = format!("sqlite:{}", path.display()); |
| 21 | |
| 22 | let db = toasty::Db::builder() |
| 23 | .models(toasty::models!(User, Repository, SshKey, Session, CiRun)) |
| 24 | .connect(&url) |
| 25 | .await?; |
| 26 | |
| 27 | if fresh { |
| 28 | db.push_schema().await?; |
| 29 | } |
| 30 | Ok(db) |
| 31 | } |