Skip to content

Commit

Permalink
Rename update_by_id to mutate_by_id
Browse files Browse the repository at this point in the history
  • Loading branch information
photino committed Dec 2, 2024
1 parent 662c82c commit 33be95e
Show file tree
Hide file tree
Showing 12 changed files with 310 additions and 64 deletions.
4 changes: 2 additions & 2 deletions examples/actix-app/src/controller/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub async fn login(mut req: Request) -> Result {
});

let mut user_mutations = user_updates.into_map_opt().unwrap_or_default();
let (validation, user) = User::update_by_id(&user_id, &mut user_mutations, None)
let (validation, user) = User::mutate_by_id(&user_id, &mut user_mutations, None)
.await
.extract(&req)?;
if !validation.is_success() {
Expand Down Expand Up @@ -45,7 +45,7 @@ pub async fn logout(req: Request) -> Result {

let mut mutations = Map::from_entry("status", "SignedOut");
let user_id = user_session.user_id();
let (validation, user) = User::update_by_id(user_id, &mut mutations, None)
let (validation, user) = User::mutate_by_id(user_id, &mut mutations, None)
.await
.extract(&req)?;
if !validation.is_success() {
Expand Down
50 changes: 25 additions & 25 deletions examples/axum-app/src/controller/auth.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
use crate::model::User;
use crate::model::{User, UserColumn::*};
use zino::{prelude::*, Request, Response, Result};
use zino_model::user::JwtAuthService;

pub async fn login(mut req: Request) -> Result {
let current_time = DateTime::now();
let body: Map = req.parse_body().await?;
let (user_id, mut data) = User::generate_token(body).await.extract(&req)?;

let user_updates = json!({
"status": "Active",
"last_login_at": data.remove("current_login_at").and_then(|v| v.as_date_time()),
"last_login_ip": data.remove("current_login_ip"),
"current_login_at": current_time,
"current_login_ip": req.client_ip(),
"$inc": { "login_count": 1 },
});

let mut user_mutations = user_updates.into_map_opt().unwrap_or_default();
let (validation, user) = User::update_by_id(&user_id, &mut user_mutations, None)
let last_login_ip = data.remove("current_login_ip");
let last_login_at = data
.remove("current_login_at")
.and_then(|v| v.as_date_time());
let mut mutation = MutationBuilder::<User>::new()
.set(Status, "Active")
.set_if_not_null(LastLoginIp, last_login_ip)
.set_if_some(LastLoginAt, last_login_at)
.set_if_some(CurrentLoginIp, req.client_ip())
.set_now(CurrentLoginAt)
.inc_one(LoginCount)
.set_now(UpdatedAt)
.inc_one(Version)
.build();
let user: User = User::update_by_id(&user_id, &mut mutation)
.await
.extract(&req)?;
if !validation.is_success() {
reject!(req, validation);
}
data.upsert("entry", user.snapshot());

let mut res = Response::default().context(&req);
Expand All @@ -41,20 +41,20 @@ pub async fn refresh(req: Request) -> Result {
pub async fn logout(req: Request) -> Result {
let user_session = req
.get_data::<UserSession<_>>()
.ok_or_else(|| warn!("401 Unauthorized: the user session is invalid"))
.ok_or_else(|| warn!("401 Unauthorized: user session is invalid"))
.extract(&req)?;

let mut mutations = Map::from_entry("status", "SignedOut");
let user_id = user_session.user_id();
let (validation, user) = User::update_by_id(user_id, &mut mutations, None)

let mut mutation = MutationBuilder::<User>::new()
.set(Status, "SignedOut")
.set_now(UpdatedAt)
.inc_one(Version)
.build();
let user: User = User::update_by_id(user_id, &mut mutation)
.await
.extract(&req)?;
if !validation.is_success() {
reject!(req, validation);
}

let data = Map::data_entry(user.snapshot());
let mut res = Response::default().context(&req);
res.set_json_data(data);
res.set_json_data(Map::data_entry(user.snapshot()));
Ok(res.into())
}
4 changes: 2 additions & 2 deletions examples/ntex-app/src/controller/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub async fn login(mut req: Request) -> Result {
});

let mut user_mutations = user_updates.into_map_opt().unwrap_or_default();
let (validation, user) = User::update_by_id(&user_id, &mut user_mutations, None)
let (validation, user) = User::mutate_by_id(&user_id, &mut user_mutations, None)
.await
.extract(&req)?;
if !validation.is_success() {
Expand Down Expand Up @@ -45,7 +45,7 @@ pub async fn logout(req: Request) -> Result {

let mut mutations = Map::from_entry("status", "SignedOut");
let user_id = user_session.user_id();
let (validation, user) = User::update_by_id(user_id, &mut mutations, None)
let (validation, user) = User::mutate_by_id(user_id, &mut mutations, None)
.await
.extract(&req)?;
if !validation.is_success() {
Expand Down
4 changes: 2 additions & 2 deletions zino-core/src/orm/accessor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,8 +407,8 @@ where
Ok(())
}

/// Updates a model of the primary key using the json object.
async fn update_by_id(
/// Mutates a model of the primary key with the JSON data and the optional extension.
async fn mutate_by_id(
id: &K,
data: &mut Map,
extension: Option<<Self as ModelHooks>::Extension>,
Expand Down
19 changes: 19 additions & 0 deletions zino-core/src/orm/mutation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,25 @@ impl<E: Entity> MutationBuilder<E> {
self
}

/// Sets the value of a column if the value is not null.
#[inline]
pub fn set_if_not_null(mut self, col: E::Column, value: impl IntoSqlValue) -> Self {
let value = value.into_sql_value();
if !value.is_null() {
self.updates.upsert(col.as_ref(), value);
}
self
}

/// Sets the value of a column if the value is not none.
#[inline]
pub fn set_if_some<T: IntoSqlValue>(mut self, col: E::Column, value: Option<T>) -> Self {
if let Some(value) = value {
self.updates.upsert(col.as_ref(), value.into_sql_value());
}
self
}

/// Sets the value of a column to the current date time.
#[inline]
pub fn set_now(mut self, col: E::Column) -> Self {
Expand Down
19 changes: 11 additions & 8 deletions zino-core/src/orm/mysql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,10 @@ impl<'c> EncodeColumn<DatabaseDriver> for Column<'c> {
name
}
};
if operator == "IN" || operator == "NOT IN" {
if let Some(subquery) = value.as_object().and_then(|m| m.get_str("$subquery")) {
let condition = format!(r#"{field} {operator} {subquery}"#);
conditions.push(condition);
} else if operator == "IN" || operator == "NOT IN" {
if let Some(values) = value.as_array() {
if values.is_empty() {
let condition = if operator == "IN" { "FALSE" } else { "TRUE" };
Expand Down Expand Up @@ -627,12 +630,12 @@ impl QueryExt<DatabaseDriver> for Query {
} else if field.contains('.') {
field
.split('.')
.map(|s| format!("`{s}`"))
.map(|s| ["`", s, "`"].concat())
.collect::<Vec<_>>()
.join(".")
.into()
} else {
format!("`{field}`").into()
["`", field, "`"].concat().into()
}
}

Expand All @@ -651,7 +654,7 @@ impl QueryExt<DatabaseDriver> for Query {
} else if field.contains('.') {
field
.split('.')
.map(|s| format!("`{s}`"))
.map(|s| ["`", s, "`"].concat())
.collect::<Vec<_>>()
.join(".")
} else {
Expand All @@ -670,7 +673,7 @@ impl QueryExt<DatabaseDriver> for Query {
if table_name.contains('.') {
let table_name = table_name
.split('.')
.map(|s| format!("`{s}`"))
.map(|s| ["`", s, "`"].concat())
.collect::<Vec<_>>()
.join(".");
format!(r#"{table_name} AS `{model_name}`"#)
Expand All @@ -684,18 +687,18 @@ impl QueryExt<DatabaseDriver> for Query {
if table_name.contains('.') {
table_name
.split('.')
.map(|s| format!("`{s}`"))
.map(|s| ["`", s, "`"].concat())
.collect::<Vec<_>>()
.join(".")
} else {
format!(r#"`{table_name}`"#)
["`", table_name, "`"].concat()
}
}

fn parse_text_search(filter: &Map) -> Option<String> {
let fields = filter.parse_str_array("$fields")?;
filter.parse_string("$search").map(|search| {
let fields = fields.join(",");
let fields = fields.join(", ");
let search = Query::escape_string(search.as_ref());
format!("match({fields}) against({search})")
})
Expand Down
17 changes: 10 additions & 7 deletions zino-core/src/orm/postgres.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,10 @@ impl<'c> EncodeColumn<DatabaseDriver> for Column<'c> {
name
}
};
if operator == "IN" || operator == "NOT IN" {
if let Some(subquery) = value.as_object().and_then(|m| m.get_str("$subquery")) {
let condition = format!(r#"{field} {operator} {subquery}"#);
conditions.push(condition);
} else if operator == "IN" || operator == "NOT IN" {
if let Some(values) = value.as_array() {
if values.is_empty() {
let condition = if operator == "IN" { "FALSE" } else { "TRUE" };
Expand Down Expand Up @@ -627,12 +630,12 @@ impl QueryExt<DatabaseDriver> for Query {
} else if field.contains('.') {
field
.split('.')
.map(|s| format!(r#""{s}""#))
.map(|s| ["\"", s, "\""].concat())
.collect::<Vec<_>>()
.join(".")
.into()
} else {
format!(r#""{field}""#).into()
["\"", field, "\""].concat().into()
}
}

Expand All @@ -651,7 +654,7 @@ impl QueryExt<DatabaseDriver> for Query {
} else if field.contains('.') {
field
.split('.')
.map(|s| format!(r#""{s}""#))
.map(|s| ["\"", s, "\""].concat())
.collect::<Vec<_>>()
.join(".")
} else {
Expand All @@ -670,7 +673,7 @@ impl QueryExt<DatabaseDriver> for Query {
if table_name.contains('.') {
let table_name = table_name
.split('.')
.map(|s| format!(r#""{s}""#))
.map(|s| ["\"", s, "\""].concat())
.collect::<Vec<_>>()
.join(".");
format!(r#"{table_name} AS "{model_name}""#)
Expand All @@ -684,11 +687,11 @@ impl QueryExt<DatabaseDriver> for Query {
if table_name.contains('.') {
table_name
.split('.')
.map(|s| format!(r#""{s}""#))
.map(|s| ["\"", s, "\""].concat())
.collect::<Vec<_>>()
.join(".")
} else {
format!(r#""{table_name}""#)
["\"", table_name, "\""].concat()
}
}

Expand Down
Loading

0 comments on commit 33be95e

Please sign in to comment.