fix in mysql

This commit is contained in:
Mateusz Gruszczyński
2026-07-27 16:11:03 +02:00
parent 326fb4050d
commit 36e0543bcd
4 changed files with 172 additions and 29 deletions
+144 -1
View File
@@ -7,7 +7,31 @@ use chrono::{DateTime, NaiveDateTime, Utc};
use rand_core::{OsRng, RngCore};
use serde::Serialize;
use sqlx::FromRow;
use sqlx::{Any, Transaction};
use sqlx::{Any, AnyRow, Row, Transaction};
fn any_text(row: &AnyRow, column: &str) -> Result<String, sqlx::Error> {
match row.try_get::<String, _>(column) {
Ok(value) => Ok(value),
Err(string_error) => match row.try_get::<Vec<u8>, _>(column) {
Ok(value) => String::from_utf8(value).map_err(|error| sqlx::Error::Decode(Box::new(error))),
Err(_) => Err(string_error),
},
}
}
fn any_optional_text(row: &AnyRow, column: &str) -> Result<Option<String>, sqlx::Error> {
match row.try_get::<Option<String>, _>(column) {
Ok(value) => Ok(value),
Err(string_error) => match row.try_get::<Option<Vec<u8>>, _>(column) {
Ok(Some(value)) => String::from_utf8(value)
.map(Some)
.map_err(|error| sqlx::Error::Decode(Box::new(error))),
Ok(None) => Ok(None),
Err(_) => Err(string_error),
},
}
}
async fn inserted_id(
kind: DatabaseKind,
@@ -37,6 +61,18 @@ pub struct Workspace {
pub is_private: i64,
}
fn workspace_from_any_row(row: AnyRow) -> Result<Workspace, sqlx::Error> {
Ok(Workspace {
id: row.try_get("id")?,
slug: any_text(&row, "slug")?,
title: any_text(&row, "title")?,
password_hash: any_optional_text(&row, "password_hash")?,
created_at: any_text(&row, "created_at")?,
updated_at: any_text(&row, "updated_at")?,
is_private: row.try_get("is_private")?,
})
}
#[derive(Debug, Clone, Serialize, FromRow)]
pub struct Note {
pub id: i64,
@@ -85,6 +121,21 @@ impl From<SqliteNote> for Note {
}
}
fn note_from_any_row(row: AnyRow) -> Result<Note, sqlx::Error> {
Ok(Note {
id: row.try_get("id")?,
_workspace_id: row.try_get("workspace_id")?,
slug: any_text(&row, "slug")?,
title: any_text(&row, "title")?,
content: any_text(&row, "content")?,
created_at: any_text(&row, "created_at")?,
updated_at: any_text(&row, "updated_at")?,
owner_map: any_text(&row, "owner_map")?,
protected: row.try_get("protected")?,
created_by: any_optional_text(&row, "created_by")?,
})
}
#[derive(Debug, Serialize, FromRow)]
pub struct Revision {
pub id: i64,
@@ -94,7 +145,25 @@ pub struct Revision {
pub owner_map: String,
}
fn revision_from_any_row(row: AnyRow) -> Result<Revision, sqlx::Error> {
Ok(Revision {
id: row.try_get("id")?,
content: any_text(&row, "content")?,
created_at: any_text(&row, "created_at")?,
author: any_optional_text(&row, "author")?,
owner_map: any_text(&row, "owner_map")?,
})
}
pub async fn find_workspace(pool: &Database, slug: &str) -> Result<Option<Workspace>, sqlx::Error> {
if pool.kind() == DatabaseKind::MySql {
return sqlx::query(queries::get(pool.kind(), queries::Q001))
.bind(slug)
.fetch_optional(pool.pool())
.await?
.map(workspace_from_any_row)
.transpose();
}
sqlx::query_as::<_, Workspace>(queries::get(pool.kind(), queries::Q001))
.bind(slug)
.fetch_optional(pool.pool())
@@ -117,6 +186,14 @@ pub async fn create_workspace(
.execute(pool.pool())
.await?;
if pool.kind() == DatabaseKind::MySql {
return workspace_from_any_row(
sqlx::query(queries::get(pool.kind(), queries::Q001))
.bind(slug)
.fetch_one(pool.pool())
.await?,
);
}
sqlx::query_as::<_, Workspace>(queries::get(pool.kind(), queries::Q001))
.bind(slug)
.fetch_one(pool.pool())
@@ -151,6 +228,15 @@ pub async fn list_notes(pool: &Database, workspace_id: i64) -> Result<Vec<Note>,
.map(Note::from)
.collect());
}
if pool.kind() == DatabaseKind::MySql {
return sqlx::query(queries::get(pool.kind(), queries::Q003))
.bind(workspace_id)
.fetch_all(pool.pool())
.await?
.into_iter()
.map(note_from_any_row)
.collect();
}
sqlx::query_as::<_, Note>(queries::get(pool.kind(), queries::Q003))
.bind(workspace_id)
.fetch_all(pool.pool())
@@ -170,6 +256,15 @@ pub async fn find_note(
.await?
.map(Note::from));
}
if pool.kind() == DatabaseKind::MySql {
return sqlx::query(queries::get(pool.kind(), queries::Q004))
.bind(workspace_id)
.bind(slug)
.fetch_optional(pool.pool())
.await?
.map(note_from_any_row)
.transpose();
}
sqlx::query_as::<_, Note>(queries::get(pool.kind(), queries::Q004))
.bind(workspace_id)
.bind(slug)
@@ -235,6 +330,15 @@ pub async fn save_revision(
}
pub async fn list_revisions(pool: &Database, note_id: i64) -> Result<Vec<Revision>, sqlx::Error> {
if pool.kind() == DatabaseKind::MySql {
return sqlx::query(queries::get(pool.kind(), queries::Q010))
.bind(note_id)
.fetch_all(pool.pool())
.await?
.into_iter()
.map(revision_from_any_row)
.collect();
}
sqlx::query_as::<_, Revision>(queries::get(pool.kind(), queries::Q010))
.bind(note_id)
.fetch_all(pool.pool())
@@ -314,7 +418,29 @@ pub struct Pad {
pub is_private: i64,
}
fn pad_from_any_row(row: AnyRow) -> Result<Pad, sqlx::Error> {
Ok(Pad {
id: row.try_get("id")?,
slug: any_text(&row, "slug")?,
title: any_text(&row, "title")?,
content: any_text(&row, "content")?,
password_hash: any_optional_text(&row, "password_hash")?,
created_at: any_text(&row, "created_at")?,
updated_at: any_text(&row, "updated_at")?,
owner_map: any_text(&row, "owner_map")?,
is_private: row.try_get("is_private")?,
})
}
pub async fn find_pad(pool: &Database, slug: &str) -> Result<Option<Pad>, sqlx::Error> {
if pool.kind() == DatabaseKind::MySql {
return sqlx::query(queries::get(pool.kind(), queries::Q011))
.bind(slug)
.fetch_optional(pool.pool())
.await?
.map(pad_from_any_row)
.transpose();
}
sqlx::query_as::<_, Pad>(queries::get(pool.kind(), queries::Q011))
.bind(slug)
.fetch_optional(pool.pool())
@@ -337,6 +463,14 @@ pub async fn create_pad(
.execute(pool.pool())
.await?;
if pool.kind() == DatabaseKind::MySql {
return pad_from_any_row(
sqlx::query(queries::get(pool.kind(), queries::Q011))
.bind(slug)
.fetch_one(pool.pool())
.await?,
);
}
sqlx::query_as::<_, Pad>(queries::get(pool.kind(), queries::Q011))
.bind(slug)
.fetch_one(pool.pool())
@@ -395,6 +529,15 @@ pub async fn list_pad_revisions(
pool: &Database,
pad_id: i64,
) -> Result<Vec<Revision>, sqlx::Error> {
if pool.kind() == DatabaseKind::MySql {
return sqlx::query(queries::get(pool.kind(), queries::Q016))
.bind(pad_id)
.fetch_all(pool.pool())
.await?
.into_iter()
.map(revision_from_any_row)
.collect();
}
sqlx::query_as::<_, Revision>(queries::get(pool.kind(), queries::Q016))
.bind(pad_id)
.fetch_all(pool.pool())