From d88948385d7f11384d32772c4f2bbc67ec9fbbab Mon Sep 17 00:00:00 2001 From: shockrah Date: Tue, 30 Mar 2021 21:38:16 -0700 Subject: [PATCH] Upgrading mysql_async to latest version This version comes with the benefit of having much more concise exec_map functionality among other things This commit and the following ones also move db-lib to using a more 'try' based approach --- json-api/db/src/member.rs | 121 ++++++++++++++------------------------ 1 file changed, 44 insertions(+), 77 deletions(-) diff --git a/json-api/db/src/member.rs b/json-api/db/src/member.rs index 22b12d1..5ef3138 100644 --- a/json-api/db/src/member.rs +++ b/json-api/db/src/member.rs @@ -1,11 +1,10 @@ -use mysql_async::{params, Pool, Conn}; +use mysql_async::{params, Pool}; use mysql_async::prelude::Queryable; -use mysql_async::error::Error as SqlError; +use mysql_async::Error as SqlError; -use crate::{Response, no_conn, sql_err}; use crate::{UBigInt, Integer, VarChar}; -use crate::{PublicMember, Member}; +use crate::{PublicMember, Member, Response}; use rand::RngCore; @@ -14,74 +13,46 @@ pub const STATUS_ONLINE: Integer = 0; pub const STATUS_OFFLINE: Integer = 1; pub const STATUS_AWAY: Integer = 2; pub const STATUS_DO_NOT_DISTURB: Integer = 3; -/* - * - * conn = getconn - * result = conn.query - * return response based on result - * - */ + impl Member { - pub async fn get(p: &Pool, id: UBigInt) -> Response { + pub async fn get(p: &Pool, id: UBigInt) -> Result, SqlError> { //! @returns Row on success //! @returns Other on failure - if let Ok(conn) = p.get_conn().await { - let q = "SELECT secret, name, status, permissions FROM members WHERE id = :id"; - type Row = Option<(VarChar, VarChar, Integer, UBigInt)>; - let db_res : Result<(Conn, Row), SqlError> - = conn.first_exec(q, params!{"id" => id}).await; - if let Ok((_, row)) = db_res { - return match row { - Some(row) => Response::Row(Self { - id, - secret: row.0, - name: row.1, - status: row.2, - permissions: row.3 - }), - None => Response::Empty - } - } - return Response::Other(sql_err!("Fetch failed")); + let mut conn = p.get_conn().await?; + + let q = "SELECT secret, name, status, permissions FROM members WHERE id = :id"; + let params = params!{"id" => id}; + + let row: Option<(VarChar, VarChar, Integer, UBigInt)> = + conn.exec_first(q, params).await?; + if let Some((secret, name, status, permissions)) = row { + Ok(Response::Row(Member { + id, secret, name, status, permissions + })) + } else { + Ok(Response::Empty) } - return Response::Other(no_conn!("Member::FromDB::get")); } - pub async fn filter(p: &Pool, status: Integer) -> Response { - //! @params status - return match (p.get_conn().await, status) { - (Ok(conn), STATUS_ONLINE) | (Ok(conn), STATUS_OFFLINE) | - (Ok(conn), STATUS_AWAY) | (Ok(conn), STATUS_DO_NOT_DISTURB) => { - // TODO: Allow people to query somewhere in the middle of this set - // i.e. we should be able to get user 100 -> 150 instead of just the - // first 1000 people - let q = - "SELECT id, name, status, permissions FROM members - WHERE status = :stat LIMIT 100"; // high limit for now - if let Ok(query) = conn.prep_exec(q, params!{"stat" => status}).await { - let mapping_r = query.map_and_drop(|row| { - let (id, name, status, permissions): (UBigInt, VarChar, Integer, UBigInt) = - mysql_async::from_row(row); + pub async fn filter(p: &Pool, status: Integer) -> Result, SqlError> { + //! @params status i32 + //! @returns Response::Set(PublicMember) + if !(status == STATUS_ONLINE || status == STATUS_AWAY || status == STATUS_OFFLINE || status == STATUS_DO_NOT_DISTURB) { + Ok(Response::RestrictedInput(format!("Invalid status"))) + } else { + let mut conn = p.get_conn().await?; + let q = + "SELECT id, name, status, permissions FROM members + WHERE status = :stat LIMIT 100"; // high limit for now - Member { - id, - secret: "".into(), // no show for obv reasons - name, - status, - permissions - } - }).await; - match mapping_r { - Ok((_, members)) => Response::Set(members), - Err(_) => Response::Other(sql_err!("db::Members::filter")) - } + let params = params!{"stat" => status}; + let members = conn.exec_map(q, params, |(id, name , status, permissions)| { + PublicMember { + id, name, status, permissions } - else { - Response::Other(sql_err!("Initial query faile: db::Members::filter")) - } - } - _ => Response::Other(sql_err!("err")) + }).await?; + Ok(Response::Set(members)) } } pub async fn add(p: &Pool, name: &str, secret: &str, perms: u64) -> Result, SqlError> { @@ -93,10 +64,10 @@ impl Member { //! @returns : on_succes => Ok(Response) //! @returns : on_partial_succes => Ok(Response) //! @returns : on_failure => Err(SomeBS) - let conn = p.get_conn().await?; + let mut conn = p.get_conn().await?; let id: u64 = rand::rngs::OsRng.next_u64(); - conn.drop_exec( + conn.exec_drop( "INSERT INTO members(secret, name, status, permissions) VALUES(:id, :secret, :name, :status, :permissions)", mysql_async::params!{ @@ -119,8 +90,8 @@ impl Member { pub async fn update_perms(p: &Pool, uid: UBigInt, permissions: UBigInt) -> Result { //! @return on_sucess Ok(NewPermisionsMask) //! @throws Err(SqlError) - let conn = p.get_conn().await?; - conn.drop_exec( + let mut conn = p.get_conn().await?; + conn.exec_drop( "UPDATE members SET permissions = :perms WHERE id = :id", params!{ "id" => uid, @@ -131,9 +102,9 @@ impl Member { } pub async fn update_nick(p: &Pool, uid: UBigInt, new_nick: &str) -> Result<(), SqlError> { - let conn = p.get_conn().await?; + let mut conn = p.get_conn().await?; - conn.drop_exec( + conn.exec_drop( "UPDATE members SET name = :nick WHERE id = id", params!{ "id" => uid, @@ -154,21 +125,17 @@ impl PublicMember { if !valid_status { return Ok(Response::RestrictedInput(format!("Invalid status value"))); } else { - let conn = p.get_conn().await?; + let mut conn = p.get_conn().await?; let q = "SELECT id, name, permissions FROM members WHERE status = :status LIMIT 1000"; - let result = conn.prep_exec(q, params!{"status" => status}).await?; - let (_, data): (_, Vec) = result.map_and_drop(|row| { - let (id, name, permissions): (UBigInt, VarChar, UBigInt) = - mysql_async::from_row(row); - + let params = params!{"status" => status}; + let members = conn.exec_map(q, params, |(id, name, permissions)| { PublicMember { id, name, permissions, status } }).await?; - return Ok(Response::Set(data)); + return Ok(Response::Set(members)); } } } -