Move all to SOA and tag time entries to join table as this should be how it works and also UNNEST doesn't support nested arrays

This commit is contained in:
Joshua Coles 2024-07-27 20:51:14 +01:00
parent 6f7db97ab6
commit 71f9ed3312
3 changed files with 58 additions and 42 deletions

View File

@ -0,0 +1,16 @@
-- Create a new join table to associate time_entries with tags
CREATE TABLE public.time_entry_tags (
time_entry_id bigint not null references public.time_entries(id) on delete cascade,
tag_id bigint not null references public.tags(id) on delete cascade,
primary key (time_entry_id, tag_id)
);
-- Insert data into the new join table based on the existing time_entries and tags data
INSERT INTO public.time_entry_tags (time_entry_id, tag_id)
SELECT time_entries.id, UNNEST(time_entries.tag_ids) AS tag_id
FROM public.time_entries
WHERE time_entries.tag_ids IS NOT NULL;
-- Remove the tag_ids array column from the time_entries table
ALTER TABLE public.time_entries
DROP COLUMN tag_ids;

View File

@ -1,7 +1,7 @@
use chrono::{DateTime, DurationRound, NaiveDate, TimeDelta, Utc}; use chrono::{DateTime, DurationRound, NaiveDate, TimeDelta, Utc};
use sqlx::{Connection, PgConnection, Postgres, QueryBuilder}; use sqlx::{Connection, PgConnection, Postgres, QueryBuilder};
use toggl::TogglApi; use toggl::TogglApi;
use crate::toggl::types::{Tag, TimeEntry, TogglReportFilters, TrackingClient}; use crate::toggl::types::{Project, Tag, TimeEntry, TogglReportFilters, TrackingClient};
use itertools::Itertools; use itertools::Itertools;
use soa_rs::Soa; use soa_rs::Soa;
use tracing_subscriber::fmt::time; use tracing_subscriber::fmt::time;
@ -218,11 +218,12 @@ impl Worker {
self.update_clients().await?; self.update_clients().await?;
} }
for project in projects { let projects: Soa<Project> = Soa::from(projects.as_slice());
sqlx::query!( sqlx::query!(
r#" r#"
INSERT INTO projects (id, workspace_id, client_id, name, color, status, active, updated_at, start_date, created_at, server_deleted_at, actual_hours, actual_seconds, can_track_time, permissions) INSERT INTO projects (id, workspace_id, client_id, name, color, status, active, updated_at, start_date, created_at, server_deleted_at, actual_hours, actual_seconds, can_track_time, permissions)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15) SELECT * FROM UNNEST($1::bigint[], $2::bigint[], $3::bigint[], $4::text[], $5::text[], $6::text[], $7::bool[], $8::timestamptz[], $9::date[], $10::timestamptz[], $11::timestamptz[], $12::int[], $13::int[], $14::bool[], $15::text[])
ON CONFLICT (id) DO UPDATE SET ON CONFLICT (id) DO UPDATE SET
workspace_id = excluded.workspace_id, workspace_id = excluded.workspace_id,
client_id = excluded.client_id, client_id = excluded.client_id,
@ -239,25 +240,24 @@ impl Worker {
can_track_time = excluded.can_track_time, can_track_time = excluded.can_track_time,
permissions = excluded.permissions permissions = excluded.permissions
"#, "#,
project.id, &projects.id().iter().map(|id| *id as i64).collect_vec()[..],
project.workspace_id, &projects.workspace_id().iter().map(|id| *id as i64).collect_vec()[..],
project.client_id, projects.client_id().iter().map(|opt| opt.map(|id| id as i64)).collect_vec() as _,
project.name, projects.name(),
project.color, projects.color(),
project.status.to_string(), &projects.status().iter().map(|s| s.to_string()).collect::<Vec<_>>()[..],
project.active, projects.active(),
project.updated_at, projects.updated_at(),
project.start_date, projects.start_date() as _,
project.created_at, projects.created_at(),
project.server_deleted_at, projects.server_deleted_at() as _,
project.actual_hours, &projects.actual_hours().iter().map(|opt| opt.map(|id| id as i64)).collect_vec() as _,
project.actual_seconds, &projects.actual_seconds().iter().map(|opt| opt.map(|id| id as i64)).collect_vec() as _,
project.can_track_time, projects.can_track_time(),
project.permissions, projects.permissions() as _,
) )
.execute(&mut self.db) .execute(&mut self.db)
.await?; .await?;
}
Ok(()) Ok(())
} }

View File

@ -304,7 +304,7 @@ pub mod types {
} }
} }
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone, Soars)]
pub struct Project { pub struct Project {
pub id: i64, pub id: i64,
pub workspace_id: i64, pub workspace_id: i64,