use sqlx::PgPool;
use uuid::Uuid;
use crate::error::Post3Error;
use crate::models::{UploadPartInfo, UploadPartRow};
pub struct UploadPartsRepository;
impl UploadPartsRepository {
pub async fn upsert(
db: &PgPool,
upload_id: Uuid,
part_number: i32,
data: &[u8],
size: i64,
etag: &str,
) -> Result<(), Post3Error> {
sqlx::query(
"INSERT INTO upload_parts (upload_id, part_number, data, size, etag) \
VALUES ($1, $2, $3, $4, $5) \
ON CONFLICT (upload_id, part_number) DO UPDATE \
SET data = EXCLUDED.data, size = EXCLUDED.size, \
etag = EXCLUDED.etag, created_at = NOW()",
)
.bind(upload_id)
.bind(part_number)
.bind(data)
.bind(size)
.bind(etag)
.execute(db)
.await?;
Ok(())
}
pub async fn list_info(
db: &PgPool,
upload_id: Uuid,
part_number_marker: Option<i32>,
max_parts: i64,
) -> Result<Vec<UploadPartInfo>, Post3Error> {
let rows = if let Some(marker) = part_number_marker {
sqlx::query_as::<_, UploadPartInfo>(
"SELECT part_number, size, etag, created_at \
FROM upload_parts \
WHERE upload_id = $1 AND part_number > $2 \
ORDER BY part_number ASC LIMIT $3",
)
.bind(upload_id)
.bind(marker)
.bind(max_parts)
.fetch_all(db)
.await?
} else {
sqlx::query_as::<_, UploadPartInfo>(
"SELECT part_number, size, etag, created_at \
FROM upload_parts \
WHERE upload_id = $1 \
ORDER BY part_number ASC LIMIT $2",
)
.bind(upload_id)
.bind(max_parts)
.fetch_all(db)
.await?
};
Ok(rows)
}
pub async fn get_ordered_by_numbers(
db: &PgPool,
upload_id: Uuid,
part_numbers: &[i32],
) -> Result<Vec<UploadPartRow>, Post3Error> {
let rows = sqlx::query_as::<_, UploadPartRow>(
"SELECT * FROM upload_parts \
WHERE upload_id = $1 AND part_number = ANY($2) \
ORDER BY part_number ASC",
)
.bind(upload_id)
.bind(part_numbers)
.fetch_all(db)
.await?;
Ok(rows)
}
}