grimhilde/ingest/src/db.rs

102 lines
2.2 KiB
Rust

// grimhilde - mirror stats
// Copyright (C) 2022 Amanda Graven and Emelie Graven
// Licensed under the EUPL
//
use std::error::Error as StdError;
use sqlx::PgPool;
use crate::Request;
/// Connect to a postgress address.
pub async fn connect(address: &str) -> sqlx::Result<PgPool> {
let pool = PgPool::connect(address).await?;
sqlx::migrate!().run(&pool).await?;
Ok(pool)
}
/// Insert a request hit into the database
pub async fn insert(pool: &PgPool, req: Request) -> Result<(), Box<dyn StdError>> {
let mut trans = pool.begin().await?;
// Get the id's for deduplicated values. Insert a value if one is missing.
sqlx::query!(
"INSERT INTO paths (path) VALUES ($1) ON CONFLICT DO NOTHING",
&req.path,
)
.execute(&mut *trans)
.await?;
sqlx::query!(
"INSERT INTO remote_addresses (addr) VALUES ($1) ON CONFLICT DO NOTHING",
&req.addr
)
.execute(&mut *trans)
.await?;
sqlx::query!(
"INSERT INTO hosts (host) VALUES ($1) ON CONFLICT DO NOTHING",
&req.host
)
.execute(&mut *trans)
.await?;
sqlx::query!(
"INSERT INTO user_agents (agent) VALUES ($1) ON CONFLICT DO NOTHING",
&req.user_agent,
)
.execute(&mut *trans)
.await?;
sqlx::query!(
"INSERT INTO referrers (referrer) VALUES ($1) ON CONFLICT DO NOTHING",
&req.referrer,
)
.execute(&mut *trans)
.await?;
let path_id = sqlx::query!("SELECT id FROM paths WHERE path = ($1)", &req.path)
.fetch_one(&mut *trans)
.await?
.id;
let path_id = sqlx::query!(
"SELECT id FROM remote_addresses WHERE addr = ($1)",
&req.addr
)
.fetch_one(&mut *trans)
.await?
.id;
let path_id = sqlx::query!("SELECT id FROM hosts WHERE host = ($1)", &req.host)
.fetch_one(&mut *trans)
.await?
.id;
let path_id = sqlx::query!(
"SELECT id FROM user_agents WHERE agent = ($1)",
&req.user_agent
)
.fetch_one(&mut *trans)
.await?
.id;
let path_id = sqlx::query!(
"SELECT id FROM referrers WHERE referrer = ($1)",
&req.referrer
)
.fetch_one(&mut *trans)
.await?
.id;
sqlx::query!(
"INSERT INTO hits (size, path, remote, host, user_agent, referrer, secure, time) \
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)",
req.size,
path_id,
remote_id,
host_id,
user_agent_id,
referrer_id,
req.secure,
req.timestamp,
)
.execute(&mut *trans)
.await?;
trans.commit().await?;
Ok(())
}