Skip to content

Commit 5a3b2f0

Browse files
committed
vingo: rewrite sql query
1 parent 3c64933 commit 5a3b2f0

File tree

5 files changed

+43
-20
lines changed

5 files changed

+43
-20
lines changed

vingo/Cargo.lock

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vingo/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,5 @@ tracing = "=0.1"
4646
tracing-subscriber = "=0.3"
4747

4848
migration = { path = "migration" }
49+
dotenvy = "0.15.7"
50+
sea-query = { version = "0.32.0", default-features = false}

vingo/migration/src/m20240903_194156_create_scan.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ pub struct Migration;
88
enum Scan {
99
Table,
1010
Id,
11-
Time,
11+
#[allow(clippy::enum_variant_names)] //TODO: rename ScanTime -> Time
12+
ScanTime,
1213
CardSerial,
1314
}
1415

@@ -22,7 +23,9 @@ impl MigrationTrait for Migration {
2223
.table(Scan::Table)
2324
.col(pk_auto(Scan::Id))
2425
.col(text(Scan::CardSerial))
25-
.col(timestamp_with_time_zone(Scan::Time).default(Expr::current_timestamp()))
26+
.col(
27+
timestamp_with_time_zone(Scan::ScanTime).default(Expr::current_timestamp()),
28+
)
2629
.foreign_key(
2730
ForeignKey::create()
2831
.from(Scan::Table, Scan::CardSerial)

vingo/src/main.rs

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ struct RegisterState {
4545

4646
#[tokio::main]
4747
async fn main() {
48+
let _ = dotenvy::dotenv();
49+
4850
tracing_subscriber::fmt()
4951
.with_max_level(tracing::Level::DEBUG)
5052
.init();

vingo/src/routes/scans.rs

+32-18
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@ use crate::{
66
};
77

88
use axum::{extract::State, Json};
9-
use chrono::{Local, Duration};
9+
use chrono::{Duration, Local};
10+
use migration::Expr;
1011
use reqwest::StatusCode;
11-
use serde::{Serialize};
1212
use sea_orm::{
13-
ActiveModelTrait, ColumnTrait, EntityTrait, JoinType::InnerJoin, QueryFilter, QuerySelect,
14-
RelationTrait, Set, FromQueryResult, entity::prelude::DateTimeWithTimeZone, Statement, DbBackend,
15-
Value
13+
entity::prelude::DateTimeWithTimeZone,
14+
ActiveModelTrait, ColumnTrait, EntityTrait, FromQueryResult, IdenStatic,
15+
JoinType::{self, InnerJoin},
16+
QueryFilter, QueryOrder, QuerySelect, RelationTrait, Set,
1617
};
18+
use serde::Serialize;
1719
use tower_sessions::Session;
1820

1921
use super::util::{
@@ -113,19 +115,31 @@ pub struct RecentScanItem {
113115

114116
pub async fn recent(state: State<AppState>) -> ResponseResult<Json<Vec<RecentScanItem>>> {
115117
let fourteen_days_ago = (Local::now() - Duration::days(14)).naive_local();
116-
let scans = RecentScanItem::find_by_statement(Statement::from_sql_and_values(DbBackend::Postgres, "
117-
SELECT DISTINCT ON (s.user_id, DATE(s.scan_time)) s.id, s.scan_time
118-
FROM (
119-
SELECT scan.id, scan.scan_time, \"user\".id as user_id
120-
FROM scan
121-
INNER JOIN card ON card.serial = scan.card_serial
122-
INNER JOIN \"user\" ON \"user\".id = card.user_id
123-
WHERE scan.scan_time > $1
124-
) s
125-
ORDER BY s.user_id, DATE(s.scan_time), s.id;", [Value::ChronoDateTime(Some(Box::new(fourteen_days_ago)))]))
126-
.all(&state.db)
127-
.await
128-
.or_log((StatusCode::INTERNAL_SERVER_ERROR, "could not get all recent scans"))?;
118+
let scans = Scan::find()
119+
.select_only()
120+
.expr(Expr::cust(format!(
121+
"DISTINCT ON ({}, DATE({})) scan.{}, scan.{}", //NOTE: this is a pain
122+
card::Column::UserId.as_str(),
123+
scan::Column::ScanTime.as_str(),
124+
scan::Column::Id.as_str(),
125+
scan::Column::ScanTime.as_str(),
126+
)))
127+
.join(JoinType::InnerJoin, scan::Relation::Card.def())
128+
.join(JoinType::InnerJoin, card::Relation::User.def())
129+
.filter(scan::Column::ScanTime.gt(fourteen_days_ago))
130+
.order_by_asc(card::Column::UserId)
131+
.order_by_asc(Expr::cust(format!(
132+
"DATE({})",
133+
scan::Column::ScanTime.as_str()
134+
)))
135+
.order_by_asc(scan::Column::Id)
136+
.into_model::<RecentScanItem>()
137+
.all(&state.db)
138+
.await
139+
.or_log((
140+
StatusCode::INTERNAL_SERVER_ERROR,
141+
"could not get all recent scans",
142+
))?;
129143

130144
Ok(Json(scans))
131145
}

0 commit comments

Comments
 (0)