fix: support sqlx 0.9

This commit is contained in:
Jon Seager 2026-06-08 10:56:18 +00:00
parent deefd10a71
commit 7563250809
8 changed files with 28 additions and 17 deletions

View file

@ -1,5 +1,5 @@
[tools]
rust = { version = "1.93", components = "rustfmt,clippy,rust-analyzer,rust-src" }
rust = { version = "1.94", components = "rustfmt,clippy,rust-analyzer,rust-src" }
node = "latest"
uv = "latest"
prek = "latest"

View file

@ -4,16 +4,23 @@
# Uses chisel to create a minimal Ubuntu rootfs for the runtime image.
# ---------------------------------------------------------------------------
# Builder — Ubuntu with Rust toolchain pre-installed
# Builder — Ubuntu with Rust toolchain installed
# ---------------------------------------------------------------------------
FROM ubuntu/rust:1.93-26.04_edge AS builder
FROM ubuntu:26.04 AS builder
ENV RUSTUP_HOME=/usr/local/rustup \
CARGO_HOME=/usr/local/cargo \
PATH=/usr/local/cargo/bin:${PATH}
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
build-essential \
pkg-config \
libssl-dev \
mold \
binutils \
curl \
&& rm -rf /var/lib/apt/lists/*
RUN curl -sSf https://sh.rustup.rs \
| sh -s -- -y --profile minimal --default-toolchain 1.94.1
# Install tailwindcss standalone (needed by build.rs)
RUN mkdir -p /usr/local/bin \

View file

@ -4,6 +4,7 @@ use anyhow::{Context, bail};
use chrono::{DateTime, NaiveDate, Utc};
use serde::{Deserialize, Serialize};
use serde_json::{from_str, to_string};
use sqlx::AssertSqlSafe;
use crate::domain::bags::Bag;
use crate::domain::brews::{Brew, QuickNote};
@ -175,7 +176,7 @@ impl BackupService {
for table in tables {
let query = format!("DELETE FROM {table}");
sqlx::query(&query)
sqlx::query(AssertSqlSafe(query))
.execute(&mut *tx)
.await
.with_context(|| format!("failed to delete from {table}"))?;
@ -316,7 +317,7 @@ impl BackupService {
for table in tables {
let query = format!("SELECT COUNT(*) as count FROM {table}");
let row: (i64,) = sqlx::query_as(&query)
let row: (i64,) = sqlx::query_as(AssertSqlSafe(query))
.fetch_one(&self.pool)
.await
.with_context(|| format!("failed to check table {table}"))?;

View file

@ -1,6 +1,6 @@
use async_trait::async_trait;
use chrono::{DateTime, NaiveDate, Utc};
use sqlx::{QueryBuilder, query_as};
use sqlx::{AssertSqlSafe, QueryBuilder, query_as};
use crate::domain::RepositoryError;
use crate::domain::bags::{Bag, BagFilter, BagSortKey, BagWithRoast, NewBag, UpdateBag};
@ -119,7 +119,7 @@ impl BagRepository for SqlBagRepository {
async fn get_with_roast(&self, id: BagId) -> Result<BagWithRoast, RepositoryError> {
let query = format!("{BASE_SELECT} WHERE b.id = ?");
let record = query_as::<_, BagWithRoastRecord>(&query)
let record = query_as::<_, BagWithRoastRecord>(AssertSqlSafe(query))
.bind(id.into_inner())
.fetch_optional(&self.pool)
.await

View file

@ -1,6 +1,6 @@
use async_trait::async_trait;
use chrono::{DateTime, Utc};
use sqlx::{QueryBuilder, query_as};
use sqlx::{AssertSqlSafe, QueryBuilder, query_as};
use crate::domain::RepositoryError;
use crate::domain::brews::{
@ -189,7 +189,7 @@ impl BrewRepository for SqlBrewRepository {
async fn get_with_details(&self, id: BrewId) -> Result<BrewWithDetails, RepositoryError> {
let query = format!("{BASE_SELECT} WHERE br.id = ?");
let record = query_as::<_, BrewWithDetailsRecord>(&query)
let record = query_as::<_, BrewWithDetailsRecord>(AssertSqlSafe(query))
.bind(id.into_inner())
.fetch_optional(&self.pool)
.await

View file

@ -1,6 +1,6 @@
use async_trait::async_trait;
use chrono::{DateTime, Utc};
use sqlx::{QueryBuilder, query, query_as};
use sqlx::{AssertSqlSafe, QueryBuilder, query, query_as};
use crate::domain::RepositoryError;
use crate::domain::cups::{Cup, CupFilter, CupSortKey, CupWithDetails, NewCup, UpdateCup};
@ -113,7 +113,7 @@ impl CupRepository for SqlCupRepository {
async fn get_with_details(&self, id: CupId) -> Result<CupWithDetails, RepositoryError> {
let query = format!("{BASE_SELECT} WHERE c.id = ?");
let record = query_as::<_, CupWithDetailsRecord>(&query)
let record = query_as::<_, CupWithDetailsRecord>(AssertSqlSafe(query))
.bind(id.into_inner())
.fetch_optional(&self.pool)
.await

View file

@ -1,4 +1,4 @@
use sqlx::{FromRow, QueryBuilder, query_scalar};
use sqlx::{AssertSqlSafe, FromRow, QueryBuilder, query_scalar};
use crate::domain::RepositoryError;
use crate::domain::listing::{ListRequest, Page, PageSize, SortKey};
@ -102,7 +102,7 @@ where
qb.push(" OFFSET ");
qb.push_bind(offset);
}
qb.build_query_as()
qb.build_query_as::<R>()
.fetch_all(pool)
.await
.map_err(|err| RepositoryError::unexpected(err.to_string()))
@ -117,13 +117,13 @@ async fn fetch_count(
let mut qb = QueryBuilder::new(count_query);
append_search_condition(&mut qb, count_query, sf);
let row: (i64,) = qb
.build_query_as()
.build_query_as::<(i64,)>()
.fetch_one(pool)
.await
.map_err(|err| RepositoryError::unexpected(err.to_string()))?;
Ok(row.0)
} else {
query_scalar(count_query)
query_scalar(AssertSqlSafe(count_query))
.fetch_one(pool)
.await
.map_err(|err| RepositoryError::unexpected(err.to_string()))
@ -131,7 +131,7 @@ async fn fetch_count(
}
fn append_search_condition(
qb: &mut QueryBuilder<'_, DatabaseDriver>,
qb: &mut QueryBuilder<DatabaseDriver>,
base_sql: &str,
search: &SearchFilter,
) {

View file

@ -233,7 +233,10 @@ async fn checkin_with_new_cafe_and_scanned_roast() {
.unwrap();
prompt_input.send_keys(Key::Enter).await.unwrap();
// Wait for scan to complete — step 3 becomes visible with the submit button
// Wait for scan to complete and populate the review before submitting.
wait_for_text(&session.driver, "body", "Kiandu AA")
.await
.unwrap();
let submit_btn = wait_for_visible(&session.driver, "button[type='submit']")
.await
.unwrap();