SOA for batch inserts using UNNEST as per docs

This commit is contained in:
2024-07-27 20:28:39 +01:00
parent ce46739f30
commit 4efbb95204
4 changed files with 53 additions and 28 deletions
+28 -26
View File
@@ -1,8 +1,9 @@
use chrono::{DateTime, DurationRound, NaiveDate, TimeDelta, Utc};
use sqlx::{Connection, PgConnection, Postgres, QueryBuilder};
use toggl::TogglApi;
use crate::toggl::types::{TimeEntry, TogglReportFilters};
use crate::toggl::types::{Tag, TimeEntry, TogglReportFilters};
use itertools::Itertools;
use soa_rs::Soa;
mod toggl;
mod sensitive;
@@ -256,31 +257,32 @@ impl Worker {
async fn update_tags(&mut self) -> Result<(), AppError> {
let tags = self.toggl_api.get_tags().await?;
let tags: Soa<Tag> = Soa::from(tags.as_slice());
for tag in tags {
sqlx::query!(
r#"
INSERT INTO tags (id, name, workspace_id, creator_id, updated_at, deleted_at, permissions)
VALUES ($1, $2, $3, $4, $5, $6, $7)
ON CONFLICT (id) DO UPDATE SET
name = excluded.name,
workspace_id = excluded.workspace_id,
creator_id = excluded.creator_id,
updated_at = excluded.updated_at,
deleted_at = excluded.deleted_at,
permissions = excluded.permissions
"#,
tag.id as i64,
tag.name,
tag.workspace_id as i64,
tag.creator_id as i64,
tag.updated_at,
tag.deleted_at,
tag.permissions,
)
.execute(&mut self.db)
.await?;
}
sqlx::query!(
r#"
INSERT INTO tags (id, name, workspace_id, creator_id, updated_at, deleted_at, permissions)
SELECT * FROM UNNEST($1::bigint[], $2::text[], $3::bigint[], $4::bigint[], $5::timestamptz[], $6::timestamptz[], $7::text[])
ON CONFLICT (id) DO UPDATE SET
name = excluded.name,
workspace_id = excluded.workspace_id,
creator_id = excluded.creator_id,
updated_at = excluded.updated_at,
deleted_at = excluded.deleted_at,
permissions = excluded.permissions
"#,
&tags.id().iter().map(|id| *id as i64).collect::<Vec<_>>()[..],
tags.name(),
&tags.workspace_id().iter().map(|id| *id as i64).collect::<Vec<_>>()[..],
&tags.creator_id().iter().map(|id| *id as i64).collect::<Vec<_>>()[..],
tags.updated_at(),
// Nullable fields fail to type check with UNNEST batch inserts so we silence the
// errors using `: _`.
tags.deleted_at(): _,
tags.permissions(): _,
)
.execute(&mut self.db)
.await?;
Ok(())
}
@@ -349,7 +351,7 @@ async fn main() {
toggl_api: api,
};
worker.update_clients()
worker.update_tags()
.await
.unwrap();
+3 -2
View File
@@ -349,7 +349,7 @@ pub mod types {
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[derive(Soars, Serialize, Deserialize, Debug, Clone)]
pub struct TrackingClient {
/// The unique identifier for the client.
pub id: i64,
@@ -378,7 +378,7 @@ pub mod types {
pub permissions: Option<String>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[derive(Soars, Serialize, Deserialize, Debug, Clone)]
pub struct Tag {
pub id: u64,
pub name: String,
@@ -493,6 +493,7 @@ pub mod types {
}
use std::fmt;
use soa_rs::Soars;
impl fmt::Debug for TogglReportFilters {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {