mirror of
https://github.com/thegeneralist01/archivr
synced 2026-07-22 03:05:32 +02:00
refactor: rename taxonomy model to tags
This commit is contained in:
parent
5b9a5bcaa4
commit
4c13ce505f
1 changed files with 33 additions and 36 deletions
|
|
@ -190,19 +190,19 @@ pub fn initialize_schema(conn: &Connection) -> Result<()> {
|
||||||
metadata_json TEXT
|
metadata_json TEXT
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS taxonomy_nodes (
|
CREATE TABLE IF NOT EXISTS tags (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
node_uid TEXT NOT NULL UNIQUE,
|
tag_uid TEXT NOT NULL UNIQUE,
|
||||||
parent_id INTEGER REFERENCES taxonomy_nodes(id),
|
parent_tag_id INTEGER REFERENCES tags(id),
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
slug TEXT NOT NULL,
|
slug TEXT NOT NULL,
|
||||||
full_path TEXT NOT NULL UNIQUE
|
full_path TEXT NOT NULL UNIQUE
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS entry_taxonomy_assignments (
|
CREATE TABLE IF NOT EXISTS entry_tag_assignments (
|
||||||
entry_id INTEGER NOT NULL REFERENCES archived_entries(id) ON DELETE CASCADE,
|
entry_id INTEGER NOT NULL REFERENCES archived_entries(id) ON DELETE CASCADE,
|
||||||
node_id INTEGER NOT NULL REFERENCES taxonomy_nodes(id) ON DELETE CASCADE,
|
tag_id INTEGER NOT NULL REFERENCES tags(id) ON DELETE CASCADE,
|
||||||
PRIMARY KEY (entry_id, node_id)
|
PRIMARY KEY (entry_id, tag_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_archive_run_items_run_id ON archive_run_items(run_id);
|
CREATE INDEX IF NOT EXISTS idx_archive_run_items_run_id ON archive_run_items(run_id);
|
||||||
|
|
@ -213,7 +213,7 @@ pub fn initialize_schema(conn: &Connection) -> Result<()> {
|
||||||
CREATE INDEX IF NOT EXISTS idx_archived_entries_visibility ON archived_entries(visibility);
|
CREATE INDEX IF NOT EXISTS idx_archived_entries_visibility ON archived_entries(visibility);
|
||||||
CREATE INDEX IF NOT EXISTS idx_entry_artifacts_entry_id ON entry_artifacts(entry_id);
|
CREATE INDEX IF NOT EXISTS idx_entry_artifacts_entry_id ON entry_artifacts(entry_id);
|
||||||
CREATE INDEX IF NOT EXISTS idx_entry_artifacts_blob_id ON entry_artifacts(blob_id);
|
CREATE INDEX IF NOT EXISTS idx_entry_artifacts_blob_id ON entry_artifacts(blob_id);
|
||||||
CREATE INDEX IF NOT EXISTS idx_taxonomy_nodes_parent_id ON taxonomy_nodes(parent_id);
|
CREATE INDEX IF NOT EXISTS idx_tags_parent_tag_id ON tags(parent_tag_id);
|
||||||
"#,
|
"#,
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -536,9 +536,9 @@ pub fn main_archive_entry_count(conn: &Connection) -> Result<i64> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub fn create_taxonomy_path(conn: &Connection, full_path: &str) -> Result<i64> {
|
pub fn create_tag_path(conn: &Connection, full_path: &str) -> Result<i64> {
|
||||||
let segments = normalized_taxonomy_segments(full_path)?;
|
let segments = normalized_tag_segments(full_path)?;
|
||||||
let mut parent_id = None;
|
let mut parent_tag_id = None;
|
||||||
let mut current_path = String::new();
|
let mut current_path = String::new();
|
||||||
let mut current_id = 0;
|
let mut current_id = 0;
|
||||||
|
|
||||||
|
|
@ -548,58 +548,58 @@ pub fn create_taxonomy_path(conn: &Connection, full_path: &str) -> Result<i64> {
|
||||||
|
|
||||||
if let Some(id) = conn
|
if let Some(id) = conn
|
||||||
.query_row(
|
.query_row(
|
||||||
"SELECT id FROM taxonomy_nodes WHERE full_path = ?1",
|
"SELECT id FROM tags WHERE full_path = ?1",
|
||||||
[current_path.as_str()],
|
[current_path.as_str()],
|
||||||
|row| row.get(0),
|
|row| row.get(0),
|
||||||
)
|
)
|
||||||
.optional()?
|
.optional()?
|
||||||
{
|
{
|
||||||
current_id = id;
|
current_id = id;
|
||||||
parent_id = Some(id);
|
parent_tag_id = Some(id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"INSERT INTO taxonomy_nodes (node_uid, parent_id, name, slug, full_path)
|
"INSERT INTO tags (tag_uid, parent_tag_id, name, slug, full_path)
|
||||||
VALUES (?1, ?2, ?3, ?4, ?5)",
|
VALUES (?1, ?2, ?3, ?4, ?5)",
|
||||||
params![
|
params![
|
||||||
public_id("node"),
|
public_id("tag"),
|
||||||
parent_id,
|
parent_tag_id,
|
||||||
humanize_slug(segment),
|
humanize_slug(segment),
|
||||||
segment,
|
segment,
|
||||||
current_path
|
current_path
|
||||||
],
|
],
|
||||||
)?;
|
)?;
|
||||||
current_id = conn.last_insert_rowid();
|
current_id = conn.last_insert_rowid();
|
||||||
parent_id = Some(current_id);
|
parent_tag_id = Some(current_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(current_id)
|
Ok(current_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub fn assign_entry_to_taxonomy(conn: &Connection, entry_id: i64, node_id: i64) -> Result<()> {
|
pub fn assign_entry_to_tag(conn: &Connection, entry_id: i64, tag_id: i64) -> Result<()> {
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"INSERT OR IGNORE INTO entry_taxonomy_assignments (entry_id, node_id)
|
"INSERT OR IGNORE INTO entry_tag_assignments (entry_id, tag_id)
|
||||||
VALUES (?1, ?2)",
|
VALUES (?1, ?2)",
|
||||||
params![entry_id, node_id],
|
params![entry_id, tag_id],
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub fn entry_count_for_taxonomy_path(conn: &Connection, full_path: &str) -> Result<i64> {
|
pub fn entry_count_for_tag_path(conn: &Connection, full_path: &str) -> Result<i64> {
|
||||||
let count = conn.query_row(
|
let count = conn.query_row(
|
||||||
"WITH RECURSIVE descendants(id) AS (
|
"WITH RECURSIVE descendants(id) AS (
|
||||||
SELECT id FROM taxonomy_nodes WHERE full_path = ?1
|
SELECT id FROM tags WHERE full_path = ?1
|
||||||
UNION ALL
|
UNION ALL
|
||||||
SELECT child.id
|
SELECT child.id
|
||||||
FROM taxonomy_nodes child
|
FROM tags child
|
||||||
JOIN descendants parent ON child.parent_id = parent.id
|
JOIN descendants parent ON child.parent_tag_id = parent.id
|
||||||
)
|
)
|
||||||
SELECT COUNT(DISTINCT eta.entry_id)
|
SELECT COUNT(DISTINCT eta.entry_id)
|
||||||
FROM entry_taxonomy_assignments eta
|
FROM entry_tag_assignments eta
|
||||||
JOIN descendants d ON eta.node_id = d.id",
|
JOIN descendants d ON eta.tag_id = d.id",
|
||||||
[full_path],
|
[full_path],
|
||||||
|row| row.get(0),
|
|row| row.get(0),
|
||||||
)?;
|
)?;
|
||||||
|
|
@ -654,7 +654,7 @@ fn validate_visibility(visibility: &str) -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn normalized_taxonomy_segments(full_path: &str) -> Result<Vec<&str>> {
|
fn normalized_tag_segments(full_path: &str) -> Result<Vec<&str>> {
|
||||||
let segments = full_path
|
let segments = full_path
|
||||||
.trim()
|
.trim()
|
||||||
.trim_matches('/')
|
.trim_matches('/')
|
||||||
|
|
@ -663,7 +663,7 @@ fn normalized_taxonomy_segments(full_path: &str) -> Result<Vec<&str>> {
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
if segments.is_empty() {
|
if segments.is_empty() {
|
||||||
bail!("taxonomy path must contain at least one segment");
|
bail!("tag path must contain at least one segment");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(segments)
|
Ok(segments)
|
||||||
|
|
@ -981,23 +981,20 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn taxonomy_assignments_are_discoverable_through_ancestors() {
|
fn hierarchical_tag_assignments_are_discoverable_through_ancestors() {
|
||||||
let conn = conn();
|
let conn = conn();
|
||||||
let entry = create_entry_fixture(&conn, "private", None, None);
|
let entry = create_entry_fixture(&conn, "private", None, None);
|
||||||
let node_id = create_taxonomy_path(&conn, "/sciences/computer-science/compilers").unwrap();
|
let tag_id = create_tag_path(&conn, "/sciences/computer-science/compilers").unwrap();
|
||||||
assign_entry_to_taxonomy(&conn, entry.id, node_id).unwrap();
|
assign_entry_to_tag(&conn, entry.id, tag_id).unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
entry_count_for_taxonomy_path(&conn, "/sciences/computer-science/compilers").unwrap(),
|
entry_count_for_tag_path(&conn, "/sciences/computer-science/compilers").unwrap(),
|
||||||
1
|
1
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
entry_count_for_taxonomy_path(&conn, "/sciences/computer-science").unwrap(),
|
entry_count_for_tag_path(&conn, "/sciences/computer-science").unwrap(),
|
||||||
1
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
entry_count_for_taxonomy_path(&conn, "/sciences").unwrap(),
|
|
||||||
1
|
1
|
||||||
);
|
);
|
||||||
|
assert_eq!(entry_count_for_tag_path(&conn, "/sciences").unwrap(), 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue