use sqlx::{PgPool, Postgres, Transaction};
use uuid::Uuid;
use crate::error::Post3Error;
use crate::models::MultipartUploadRow;
pub struct MultipartUploadsRepository;
impl MultipartUploadsRepository {
pub async fn create_in_tx(
tx: &mut Transaction<'_, Postgres>,
bucket_id: Uuid,
key: &str,
upload_id: &str,
content_type: &str,
) -> Result<MultipartUploadRow, Post3Error> {
let row = sqlx::query_as::<_, MultipartUploadRow>(
"INSERT INTO multipart_uploads (bucket_id, key, upload_id, content_type) \
VALUES ($1, $2, $3, $4) RETURNING *",
)
.bind(bucket_id)
.bind(key)
.bind(upload_id)
.bind(content_type)
.fetch_one(&mut **tx)
.await?;
Ok(row)
}
pub async fn get_by_upload_id(
db: &PgPool,
upload_id: &str,
) -> Result<Option<MultipartUploadRow>, Post3Error> {
let row = sqlx::query_as::<_, MultipartUploadRow>(
"SELECT * FROM multipart_uploads WHERE upload_id = $1",
)
.bind(upload_id)
.fetch_optional(db)
.await?;
Ok(row)
}
pub async fn delete_in_tx(
tx: &mut Transaction<'_, Postgres>,
id: Uuid,
) -> Result<(), Post3Error> {
sqlx::query("DELETE FROM multipart_uploads WHERE id = $1")
.bind(id)
.execute(&mut **tx)
.await?;
Ok(())
}
pub async fn delete_by_upload_id(
db: &PgPool,
upload_id: &str,
) -> Result<bool, Post3Error> {
let result = sqlx::query("DELETE FROM multipart_uploads WHERE upload_id = $1")
.bind(upload_id)
.execute(db)
.await?;
Ok(result.rows_affected() > 0)
}
pub async fn list(
db: &PgPool,
bucket_id: Uuid,
prefix: Option<&str>,
key_marker: Option<&str>,
upload_id_marker: Option<&str>,
max_uploads: i64,
) -> Result<Vec<MultipartUploadRow>, Post3Error> {
let rows = match (prefix, key_marker) {
(Some(pfx), Some(marker)) => {
let pattern = format!("{pfx}%");
if let Some(uid_marker) = upload_id_marker {
sqlx::query_as::<_, MultipartUploadRow>(
"SELECT * FROM multipart_uploads \
WHERE bucket_id = $1 AND key LIKE $2 \
AND (key > $3 OR (key = $3 AND upload_id > $4)) \
ORDER BY key ASC, upload_id ASC LIMIT $5",
)
.bind(bucket_id)
.bind(pattern)
.bind(marker)
.bind(uid_marker)
.bind(max_uploads)
.fetch_all(db)
.await?
} else {
sqlx::query_as::<_, MultipartUploadRow>(
"SELECT * FROM multipart_uploads \
WHERE bucket_id = $1 AND key LIKE $2 AND key > $3 \
ORDER BY key ASC, upload_id ASC LIMIT $4",
)
.bind(bucket_id)
.bind(pattern)
.bind(marker)
.bind(max_uploads)
.fetch_all(db)
.await?
}
}
(Some(pfx), None) => {
let pattern = format!("{pfx}%");
sqlx::query_as::<_, MultipartUploadRow>(
"SELECT * FROM multipart_uploads \
WHERE bucket_id = $1 AND key LIKE $2 \
ORDER BY key ASC, upload_id ASC LIMIT $3",
)
.bind(bucket_id)
.bind(pattern)
.bind(max_uploads)
.fetch_all(db)
.await?
}
(None, Some(marker)) => {
if let Some(uid_marker) = upload_id_marker {
sqlx::query_as::<_, MultipartUploadRow>(
"SELECT * FROM multipart_uploads \
WHERE bucket_id = $1 \
AND (key > $2 OR (key = $2 AND upload_id > $3)) \
ORDER BY key ASC, upload_id ASC LIMIT $4",
)
.bind(bucket_id)
.bind(marker)
.bind(uid_marker)
.bind(max_uploads)
.fetch_all(db)
.await?
} else {
sqlx::query_as::<_, MultipartUploadRow>(
"SELECT * FROM multipart_uploads \
WHERE bucket_id = $1 AND key > $2 \
ORDER BY key ASC, upload_id ASC LIMIT $3",
)
.bind(bucket_id)
.bind(marker)
.bind(max_uploads)
.fetch_all(db)
.await?
}
}
(None, None) => {
sqlx::query_as::<_, MultipartUploadRow>(
"SELECT * FROM multipart_uploads \
WHERE bucket_id = $1 \
ORDER BY key ASC, upload_id ASC LIMIT $2",
)
.bind(bucket_id)
.bind(max_uploads)
.fetch_all(db)
.await?
}
};
Ok(rows)
}
}