Simplify database schema
This commit is contained in:
@@ -3,6 +3,9 @@ use anyhow::{
|
||||
Context,
|
||||
Result,
|
||||
};
|
||||
use chrono::{
|
||||
Utc,
|
||||
};
|
||||
use clap::{
|
||||
Parser,
|
||||
};
|
||||
@@ -167,6 +170,8 @@ struct Cli {
|
||||
async fn main() -> Result<()> {
|
||||
let cli = Cli::parse();
|
||||
|
||||
let scan_time = Utc::now().timestamp();
|
||||
|
||||
let db = SqlitePoolOptions::new().connect("sqlite://flake-tracker.db").await?;
|
||||
|
||||
let flake_metadata_raw = Command::new("nix")
|
||||
@@ -180,21 +185,21 @@ async fn main() -> Result<()> {
|
||||
let flake_metadata: FlakeMetadata = serde_json::from_slice(&flake_metadata_raw.stdout)
|
||||
.context("Failed to parse flake metadata")?;
|
||||
|
||||
sqlx::query("INSERT INTO flake_revisions (revision_uri, uri, nix_store_path, revision, nar_hash, last_modified)
|
||||
sqlx::query("INSERT INTO revisions (revision_uri, flake_uri, nix_store_path, nar_hash, last_modified, tracker_last_scanned)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(revision_uri) DO UPDATE SET
|
||||
uri=excluded.uri,
|
||||
flake_uri=excluded.flake_uri,
|
||||
nix_store_path=excluded.nix_store_path,
|
||||
revision=excluded.revision,
|
||||
nar_hash=excluded.nar_hash,
|
||||
last_modified=excluded.last_modified
|
||||
last_modified=excluded.last_modified,
|
||||
tracker_last_scanned=excluded.tracker_last_scanned
|
||||
")
|
||||
.bind(&flake_metadata.locked.flake_uri()?)
|
||||
.bind(&flake_metadata.resolved.flake_uri()?)
|
||||
.bind(&flake_metadata.path)
|
||||
.bind(&flake_metadata.revision)
|
||||
.bind(&flake_metadata.locked.narHash)
|
||||
.bind(&flake_metadata.locked.lastModified)
|
||||
.bind(&scan_time)
|
||||
.execute(&db).await?;
|
||||
|
||||
let locks_root_name = &flake_metadata.locks.root;
|
||||
@@ -207,12 +212,12 @@ async fn main() -> Result<()> {
|
||||
let locks_input_node = flake_metadata.locks.nodes.get(&locks_input_name)
|
||||
.context("Failed to find lock of input")?;
|
||||
|
||||
sqlx::query("INSERT INTO flake_revisions_inputs (flake_revision_uri, input_name, revision_uri, uri, nar_hash, last_modified)
|
||||
sqlx::query("INSERT INTO inputs (revision_uri, input_name, locked_revision_uri, locked_flake_uri, locked_nar_hash, last_modified)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(flake_revision_uri, input_name) DO UPDATE SET
|
||||
revision_uri=excluded.revision_uri,
|
||||
uri=excluded.uri,
|
||||
nar_hash=excluded.nar_hash,
|
||||
ON CONFLICT(revision_uri, input_name) DO UPDATE SET
|
||||
locked_revision_uri=excluded.locked_revision_uri,
|
||||
locked_flake_uri=excluded.locked_flake_uri,
|
||||
locked_nar_hash=excluded.locked_nar_hash,
|
||||
last_modified=excluded.last_modified
|
||||
")
|
||||
.bind(flake_metadata.locked.flake_uri()?)
|
||||
@@ -222,6 +227,14 @@ async fn main() -> Result<()> {
|
||||
.bind(locks_input_node.locked.clone().context("Unexpected missing lock")?.narHash)
|
||||
.bind(locks_input_node.locked.clone().context("Unexpected missing lock")?.lastModified)
|
||||
.execute(&db).await?;
|
||||
|
||||
sqlx::query("INSERT INTO revisions (revision_uri, flake_uri)
|
||||
VALUES (?, ?)
|
||||
ON CONFLICT(revision_uri) DO NOTHING
|
||||
")
|
||||
.bind(locks_input_node.locked.clone().context("Unexpected missing lock")?.flake_uri()?)
|
||||
.bind(locks_input_node.original.clone().context("Unexpected missing lock")?.flake_uri()?)
|
||||
.execute(&db).await?;
|
||||
}
|
||||
}
|
||||
|
||||
|
108
src/storage.rs
108
src/storage.rs
@@ -31,15 +31,9 @@ impl Storage {
|
||||
pub async fn flakes(&self) -> Result<Vec<FlakeUri>> {
|
||||
sqlx::query_as("
|
||||
SELECT
|
||||
uri
|
||||
FROM flake_revisions
|
||||
UNION
|
||||
SELECT
|
||||
uri
|
||||
FROM flake_revisions_inputs
|
||||
WHERE uri IS NOT NULL
|
||||
GROUP BY uri
|
||||
ORDER BY uri
|
||||
flake_uri
|
||||
FROM revisions
|
||||
ORDER BY flake_uri
|
||||
")
|
||||
.fetch_all(&self.db)
|
||||
.await
|
||||
@@ -51,18 +45,11 @@ impl Storage {
|
||||
SELECT
|
||||
revision_uri,
|
||||
last_modified
|
||||
FROM flake_revisions
|
||||
WHERE uri = ?
|
||||
UNION
|
||||
SELECT
|
||||
revision_uri,
|
||||
last_modified
|
||||
FROM flake_revisions_inputs
|
||||
WHERE uri = ?
|
||||
FROM revisions
|
||||
WHERE flake_uri = ?
|
||||
ORDER BY last_modified DESC
|
||||
")
|
||||
.bind(&uri)
|
||||
.bind(&uri)
|
||||
.fetch_all(&self.db)
|
||||
.await
|
||||
.context("Failed to fetch data from database")
|
||||
@@ -71,14 +58,14 @@ impl Storage {
|
||||
pub async fn inputs_for_revision(&self, revision_uri: &str) -> Result<Vec<InputModel>> {
|
||||
sqlx::query_as("
|
||||
SELECT
|
||||
flake_revision_uri,
|
||||
input_name,
|
||||
revision_uri,
|
||||
uri,
|
||||
nar_hash,
|
||||
input_name,
|
||||
locked_revision_uri,
|
||||
locked_flake_uri,
|
||||
locked_nar_hash,
|
||||
last_modified
|
||||
FROM flake_revisions_inputs
|
||||
WHERE flake_revision_uri = ?
|
||||
FROM inputs
|
||||
WHERE revision_uri = ?
|
||||
ORDER BY input_name
|
||||
")
|
||||
.bind(&revision_uri)
|
||||
@@ -90,14 +77,14 @@ impl Storage {
|
||||
pub async fn input_of_for_revision(&self, revision_uri: &str) -> Result<Vec<InputModel>> {
|
||||
sqlx::query_as("
|
||||
SELECT
|
||||
flake_revision_uri,
|
||||
input_name,
|
||||
revision_uri,
|
||||
uri,
|
||||
nar_hash,
|
||||
input_name,
|
||||
locked_revision_uri,
|
||||
locked_flake_uri,
|
||||
locked_nar_hash,
|
||||
last_modified
|
||||
FROM flake_revisions_inputs
|
||||
WHERE revision_uri = ?
|
||||
FROM inputs
|
||||
WHERE locked_revision_uri = ?
|
||||
ORDER BY input_name
|
||||
")
|
||||
.bind(&revision_uri)
|
||||
@@ -110,20 +97,20 @@ impl Storage {
|
||||
sqlx::query_as("
|
||||
|
||||
SELECT
|
||||
flake_revisions.revision_uri,
|
||||
MAX(flake_revisions.last_modified) AS last_modified,
|
||||
flake_revisions_inputs.input_name,
|
||||
flake_revisions_inputs.uri
|
||||
revisions.revision_uri,
|
||||
MAX(revisions.last_modified) AS last_modified,
|
||||
inputs.input_name,
|
||||
inputs.locked_flake_uri
|
||||
FROM
|
||||
flake_revisions
|
||||
revisions
|
||||
LEFT JOIN
|
||||
flake_revisions_inputs
|
||||
inputs
|
||||
ON
|
||||
flake_revisions.revision_uri = flake_revisions_inputs.flake_revision_uri
|
||||
revisions.revision_uri = inputs.revision_uri
|
||||
WHERE
|
||||
flake_revisions.uri = ?
|
||||
revisions.flake_uri = ?
|
||||
GROUP BY
|
||||
flake_revisions_inputs.input_name
|
||||
inputs.input_name
|
||||
")
|
||||
.bind(&flake_uri)
|
||||
.fetch_all(&self.db)
|
||||
@@ -135,9 +122,8 @@ impl Storage {
|
||||
#[derive(FromRow)]
|
||||
pub struct FlakeRevisionRow {
|
||||
pub revision_uri: String,
|
||||
pub uri: Option<String>,
|
||||
pub flake_uri: Option<String>,
|
||||
pub nix_store_path: Option<String>,
|
||||
pub revision: Option<String>,
|
||||
pub nar_hash: Option<String>,
|
||||
pub last_modified: Option<i64>,
|
||||
}
|
||||
@@ -147,13 +133,13 @@ pub struct InputForFlakeRow {
|
||||
pub revision_uri: String,
|
||||
pub last_modified: Option<i64>,
|
||||
pub input_name: String,
|
||||
pub uri: Option<String>,
|
||||
pub locked_flake_uri: Option<String>,
|
||||
}
|
||||
|
||||
impl InputForFlakeRow {
|
||||
pub fn flake_link(&self ) -> String {
|
||||
match &self.uri {
|
||||
Some(uri) => format!("/f/{}", urlencode(&uri)),
|
||||
pub fn locked_flake_link(&self ) -> String {
|
||||
match &self.locked_flake_uri {
|
||||
Some(locked_flake_uri) => format!("/f/{}", urlencode(&locked_flake_uri)),
|
||||
None => String::from("#"),
|
||||
}
|
||||
}
|
||||
@@ -167,47 +153,47 @@ pub struct RevisionListModel {
|
||||
}
|
||||
|
||||
impl RevisionListModel {
|
||||
pub fn link(&self ) -> String {
|
||||
pub fn revision_link(&self ) -> String {
|
||||
format!("/r/{}", urlencode(&self.revision_uri))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(FromRow)]
|
||||
pub struct FlakeUri {
|
||||
pub uri: String,
|
||||
pub flake_uri: String,
|
||||
}
|
||||
|
||||
impl FlakeUri {
|
||||
pub fn link(&self ) -> String {
|
||||
format!("/f/{}", urlencode(&self.uri))
|
||||
pub fn flake_link(&self ) -> String {
|
||||
format!("/f/{}", urlencode(&self.flake_uri))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(FromRow)]
|
||||
pub struct InputModel {
|
||||
pub flake_revision_uri: String,
|
||||
pub revision_uri: String,
|
||||
pub input_name: String,
|
||||
pub revision_uri: Option<String>,
|
||||
pub uri: Option<String>,
|
||||
pub nar_hash: Option<String>,
|
||||
pub locked_revision_uri: Option<String>,
|
||||
pub locked_flake_uri: Option<String>,
|
||||
pub locked_nar_hash: Option<String>,
|
||||
pub last_modified: Option<i64>,
|
||||
}
|
||||
|
||||
impl InputModel {
|
||||
pub fn flake_revision_link(&self) -> String {
|
||||
format!("/r/{}", urlencode(&self.flake_revision_uri))
|
||||
pub fn revision_link(&self) -> String {
|
||||
format!("/r/{}", urlencode(&self.revision_uri))
|
||||
}
|
||||
|
||||
pub fn revision_link(&self) -> String {
|
||||
match &self.revision_uri {
|
||||
Some(revision_uri) => format!("/r/{}", urlencode(&revision_uri)),
|
||||
pub fn locked_revision_link(&self) -> String {
|
||||
match &self.locked_revision_uri {
|
||||
Some(locked_revision_uri) => format!("/r/{}", urlencode(&locked_revision_uri)),
|
||||
None => String::from("#"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn flake_link(&self) -> String {
|
||||
match &self.uri {
|
||||
Some(uri) => format!("/f/{}", urlencode(&uri)),
|
||||
pub fn locked_flake_link(&self) -> String {
|
||||
match &self.locked_flake_uri {
|
||||
Some(locked_flake_uri) => format!("/f/{}", urlencode(&locked_flake_uri)),
|
||||
None => String::from("#"),
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user