// 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 { 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> { let mut trans = pool.begin().await?; // Get the id's for deduplicated values. Insert a value if one is missing. let path_id = sqlx::query!( "INSERT INTO paths (path) VALUES ($1) ON CONFLICT DO NOTHING RETURNING id", &req.path, ).fetch_one(&mut *trans).await?.id; let remote_id = sqlx::query!( "INSERT INTO remote_addresses (addr) VALUES ($1) ON CONFLICT DO NOTHING RETURNING id", req.addr) .fetch_one(&mut *trans).await?.id; let host_id = sqlx::query!( "INSERT INTO hosts (host) VALUES ($1) ON CONFLICT DO NOTHING RETURNING id", &req.host) .fetch_one(&mut *trans).await?.id; let user_agent_id = sqlx::query!( "INSERT INTO user_agents (agent) VALUES ($1) ON CONFLICT DO NOTHING RETURNING id", &req.user_agent, ).fetch_one(&mut *trans).await?.id; let referrer_id = sqlx::query!( "INSERT INTO referrers (referrer) VALUES ($1) ON CONFLICT DO NOTHING RETURNING id", &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(()) }