diff --git a/src/backend/postgres/mod.rs b/src/backend/postgres/mod.rs index 99f378144..8e775c73c 100644 --- a/src/backend/postgres/mod.rs +++ b/src/backend/postgres/mod.rs @@ -150,7 +150,7 @@ mod tests { for b in 0u8..=31 { let c = b as char; if !matches!(c, '\x00' | '\x08' | '\x09' | '\x0A' | '\x0C' | '\x0D') { - let octal = format!("\\{:03o}", b); + let octal = format!("\\{b:03o}"); assert!(escaped.contains(&octal)); } } diff --git a/src/backend/postgres/query.rs b/src/backend/postgres/query.rs index 547c5cd18..194619850 100644 --- a/src/backend/postgres/query.rs +++ b/src/backend/postgres/query.rs @@ -320,6 +320,17 @@ impl QueryBuilder for PostgresQueryBuilder { PgFunc::Any => "ANY", PgFunc::Some => "SOME", PgFunc::All => "ALL", + PgFunc::AdvisoryLock => "PG_ADVISORY_LOCK", + PgFunc::AdvisoryLockShared => "PG_ADVISORY_LOCK_SHARED", + PgFunc::TryAdvisoryLock => "PG_TRY_ADVISORY_LOCK", + PgFunc::TryAdvisoryLockShared => "PG_TRY_ADVISORY_LOCK_SHARED", + PgFunc::AdvisoryUnlock => "PG_ADVISORY_UNLOCK", + PgFunc::AdvisoryUnlockShared => "PG_ADVISORY_UNLOCK_SHARED", + PgFunc::AdvisoryUnlockAll => "PG_ADVISORY_UNLOCK_ALL", + PgFunc::AdvisoryXactLock => "PG_ADVISORY_XACT_LOCK", + PgFunc::AdvisoryXactLockShared => "PG_ADVISORY_XACT_LOCK_SHARED", + PgFunc::TryAdvisoryXactLock => "PG_TRY_ADVISORY_XACT_LOCK", + PgFunc::TryAdvisoryXactLockShared => "PG_TRY_ADVISORY_XACT_LOCK_SHARED", }) .unwrap(), _ => self.prepare_function_name_common(function, sql), diff --git a/src/extension/postgres/func.rs b/src/extension/postgres/func.rs index 716411f8e..2755a9a1a 100644 --- a/src/extension/postgres/func.rs +++ b/src/extension/postgres/func.rs @@ -32,6 +32,17 @@ pub enum PgFunc { Any, Some, All, + AdvisoryLock, + AdvisoryLockShared, + TryAdvisoryLock, + TryAdvisoryLockShared, + AdvisoryUnlock, + AdvisoryUnlockShared, + AdvisoryUnlockAll, + AdvisoryXactLock, + AdvisoryXactLockShared, + TryAdvisoryXactLock, + TryAdvisoryXactLockShared, } impl From for Func { @@ -522,4 +533,254 @@ impl PgFunc { { FunctionCall::new(PgFunc::ArrayAgg).arg_with(expr, FuncArgMod { distinct: true }) } + + /// Call `PG_ADVISORY_LOCK` function. Postgres only. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .expr(PgFunc::advisory_lock(Expr::val(12345_i64))) + /// .to_owned(); + /// + /// assert_eq!( + /// query.to_string(PostgresQueryBuilder), + /// r#"SELECT PG_ADVISORY_LOCK(12345)"# + /// ); + /// ``` + pub fn advisory_lock(key: T) -> FunctionCall + where + T: Into, + { + FunctionCall::new(PgFunc::AdvisoryLock).arg(key) + } + + /// Call `PG_ADVISORY_LOCK_SHARED` function. Postgres only. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .expr(PgFunc::advisory_lock_shared(Expr::val(12345_i64))) + /// .to_owned(); + /// + /// assert_eq!( + /// query.to_string(PostgresQueryBuilder), + /// r#"SELECT PG_ADVISORY_LOCK_SHARED(12345)"# + /// ); + /// ``` + pub fn advisory_lock_shared(key: T) -> FunctionCall + where + T: Into, + { + FunctionCall::new(PgFunc::AdvisoryLockShared).arg(key) + } + + /// Call `PG_TRY_ADVISORY_LOCK` function. Postgres only. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .expr(PgFunc::try_advisory_lock(Expr::val(12345_i64))) + /// .to_owned(); + /// + /// assert_eq!( + /// query.to_string(PostgresQueryBuilder), + /// r#"SELECT PG_TRY_ADVISORY_LOCK(12345)"# + /// ); + /// ``` + pub fn try_advisory_lock(key: T) -> FunctionCall + where + T: Into, + { + FunctionCall::new(PgFunc::TryAdvisoryLock).arg(key) + } + + /// Call `PG_TRY_ADVISORY_LOCK_SHARED` function. Postgres only. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .expr(PgFunc::try_advisory_lock_shared(Expr::val(12345_i64))) + /// .to_owned(); + /// + /// assert_eq!( + /// query.to_string(PostgresQueryBuilder), + /// r#"SELECT PG_TRY_ADVISORY_LOCK_SHARED(12345)"# + /// ); + /// ``` + pub fn try_advisory_lock_shared(key: T) -> FunctionCall + where + T: Into, + { + FunctionCall::new(PgFunc::TryAdvisoryLockShared).arg(key) + } + + /// Call `PG_ADVISORY_UNLOCK` function. Postgres only. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .expr(PgFunc::advisory_unlock(Expr::val(12345_i64))) + /// .to_owned(); + /// + /// assert_eq!( + /// query.to_string(PostgresQueryBuilder), + /// r#"SELECT PG_ADVISORY_UNLOCK(12345)"# + /// ); + /// ``` + pub fn advisory_unlock(key: T) -> FunctionCall + where + T: Into, + { + FunctionCall::new(PgFunc::AdvisoryUnlock).arg(key) + } + + /// Call `PG_ADVISORY_UNLOCK_SHARED` function. Postgres only. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .expr(PgFunc::advisory_unlock_shared(Expr::val(12345_i64))) + /// .to_owned(); + /// + /// assert_eq!( + /// query.to_string(PostgresQueryBuilder), + /// r#"SELECT PG_ADVISORY_UNLOCK_SHARED(12345)"# + /// ); + /// ``` + pub fn advisory_unlock_shared(key: T) -> FunctionCall + where + T: Into, + { + FunctionCall::new(PgFunc::AdvisoryUnlockShared).arg(key) + } + + /// Call `PG_ADVISORY_UNLOCK_ALL` function. Postgres only. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .expr(PgFunc::advisory_unlock_all()) + /// .to_owned(); + /// + /// assert_eq!( + /// query.to_string(PostgresQueryBuilder), + /// r#"SELECT PG_ADVISORY_UNLOCK_ALL()"# + /// ); + /// ``` + pub fn advisory_unlock_all() -> FunctionCall { + FunctionCall::new(PgFunc::AdvisoryUnlockAll) + } + + /// Call `PG_ADVISORY_XACT_LOCK` function. Postgres only. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .expr(PgFunc::advisory_xact_lock(Expr::val(12345_i64))) + /// .to_owned(); + /// + /// assert_eq!( + /// query.to_string(PostgresQueryBuilder), + /// r#"SELECT PG_ADVISORY_XACT_LOCK(12345)"# + /// ); + /// ``` + pub fn advisory_xact_lock(key: T) -> FunctionCall + where + T: Into, + { + FunctionCall::new(PgFunc::AdvisoryXactLock).arg(key) + } + + /// Call `PG_ADVISORY_XACT_LOCK_SHARED` function. Postgres only. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .expr(PgFunc::advisory_xact_lock_shared(Expr::val(12345_i64))) + /// .to_owned(); + /// + /// assert_eq!( + /// query.to_string(PostgresQueryBuilder), + /// r#"SELECT PG_ADVISORY_XACT_LOCK_SHARED(12345)"# + /// ); + /// ``` + pub fn advisory_xact_lock_shared(key: T) -> FunctionCall + where + T: Into, + { + FunctionCall::new(PgFunc::AdvisoryXactLockShared).arg(key) + } + + /// Call `PG_TRY_ADVISORY_XACT_LOCK` function. Postgres only. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .expr(PgFunc::try_advisory_xact_lock(Expr::val(12345_i64))) + /// .to_owned(); + /// + /// assert_eq!( + /// query.to_string(PostgresQueryBuilder), + /// r#"SELECT PG_TRY_ADVISORY_XACT_LOCK(12345)"# + /// ); + /// ``` + pub fn try_advisory_xact_lock(key: T) -> FunctionCall + where + T: Into, + { + FunctionCall::new(PgFunc::TryAdvisoryXactLock).arg(key) + } + + /// Call `PG_TRY_ADVISORY_XACT_LOCK_SHARED` function. Postgres only. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .expr(PgFunc::try_advisory_xact_lock_shared(Expr::val(12345_i64))) + /// .to_owned(); + /// + /// assert_eq!( + /// query.to_string(PostgresQueryBuilder), + /// r#"SELECT PG_TRY_ADVISORY_XACT_LOCK_SHARED(12345)"# + /// ); + /// ``` + pub fn try_advisory_xact_lock_shared(key: T) -> FunctionCall + where + T: Into, + { + FunctionCall::new(PgFunc::TryAdvisoryXactLockShared).arg(key) + } } diff --git a/src/raw_sql.rs b/src/raw_sql.rs index b1af01187..7ed9527ef 100644 --- a/src/raw_sql.rs +++ b/src/raw_sql.rs @@ -81,7 +81,7 @@ mod test { #[test] fn test_raw_sql_1() { let a = 1; - let b = vec![2i32, 3]; + let b = [2i32, 3]; let c = [4i32, 5, 6]; let mut builder = RawSqlQueryBuilder::new(PostgresQueryBuilder); @@ -90,18 +90,18 @@ mod test { .push_fragment(" ") .push_parameters(1) .push_fragment(", ") - .push_parameters((&b).len()) + .push_parameters(b.len()) .push_fragment(", ") - .push_parameters((&c).len()); + .push_parameters(c.len()); assert_eq!(builder.finish(), "SELECT $1, $2, $3, $4, $5, $6"); let mut values = Values::default(); values.bind(a); - for v in (&b).iter() { + for v in b.iter() { values.bind(v); } - for v in (&c).iter() { + for v in c.iter() { values.bind(v); } diff --git a/tests/mysql/query.rs b/tests/mysql/query.rs index b1415a7c9..98276317d 100644 --- a/tests/mysql/query.rs +++ b/tests/mysql/query.rs @@ -1092,7 +1092,9 @@ fn insert_4() { Query::insert() .into_table(Glyph::Table) .columns([Glyph::Image]) - .values_panic([chrono::NaiveDateTime::from_timestamp_opt(0, 0) + .values_panic([chrono::NaiveDate::from_ymd_opt(1970, 1, 1) + .unwrap() + .and_hms_opt(0, 0, 0) .unwrap() .into()]) .to_string(MysqlQueryBuilder), diff --git a/tests/postgres/query.rs b/tests/postgres/query.rs index dfff63007..06dd18c48 100644 --- a/tests/postgres/query.rs +++ b/tests/postgres/query.rs @@ -1,6 +1,8 @@ +use core::f64; + use super::*; use pretty_assertions::assert_eq; -use sea_query::{ExplainFormat, audit::AuditTrait, extension::postgres::PgBinOper}; +use sea_query::{audit::AuditTrait, extension::postgres::PgBinOper}; #[test] fn select_1() { @@ -1283,12 +1285,12 @@ fn insert_2() { .columns([Glyph::Image, Glyph::Aspect]) .values_panic([ "04108048005887010020060000204E0180400400".into(), - 3.1415.into(), + f64::consts::PI.into(), ]) .take(); assert_eq!( query.to_string(PostgresQueryBuilder), - r#"INSERT INTO "glyph" ("image", "aspect") VALUES ('04108048005887010020060000204E0180400400', 3.1415)"# + r#"INSERT INTO "glyph" ("image", "aspect") VALUES ('04108048005887010020060000204E0180400400', 3.141592653589793)"# ); assert_eq!( query.audit_unwrap().inserted_tables(), @@ -1305,11 +1307,11 @@ fn insert_3() { .columns([Glyph::Image, Glyph::Aspect]) .values_panic([ "04108048005887010020060000204E0180400400".into(), - 3.1415.into(), + f64::consts::PI.into(), ]) .values_panic([Value::String(None).into(), 2.1345.into()]) .to_string(PostgresQueryBuilder), - r#"INSERT INTO "glyph" ("image", "aspect") VALUES ('04108048005887010020060000204E0180400400', 3.1415), (NULL, 2.1345)"# + r#"INSERT INTO "glyph" ("image", "aspect") VALUES ('04108048005887010020060000204E0180400400', 3.141592653589793), (NULL, 2.1345)"# ); } @@ -1364,7 +1366,9 @@ fn insert_4() { Query::insert() .into_table(Glyph::Table) .columns([Glyph::Image]) - .values_panic([chrono::NaiveDateTime::from_timestamp_opt(0, 0) + .values_panic([chrono::NaiveDate::from_ymd_opt(1970, 1, 1) + .unwrap() + .and_hms_opt(0, 0, 0) .unwrap() .into()]) .to_string(PostgresQueryBuilder), @@ -1526,7 +1530,7 @@ fn insert_10() { .into_table(Glyph::Table) .columns([Glyph::Aspect, Glyph::Tokens]) .values_panic([ - 3.1415.into(), + f64::consts::PI.into(), vec![ "Token1".to_string(), "Token2".to_string(), @@ -1535,7 +1539,7 @@ fn insert_10() { .into() ]) .to_string(PostgresQueryBuilder), - r#"INSERT INTO "glyph" ("aspect", "tokens") VALUES (3.1415, ARRAY ['Token1','Token2','Token3'])"# + r#"INSERT INTO "glyph" ("aspect", "tokens") VALUES (3.141592653589793, ARRAY ['Token1','Token2','Token3'])"# ); } @@ -1547,9 +1551,9 @@ fn insert_issue_853() { Query::insert() .into_table(Glyph::Table) .columns([Glyph::Aspect, Glyph::Tokens]) - .values_panic([3.1415.into(), Vec::::new().into()]) + .values_panic([f64::consts::PI.into(), Vec::::new().into()]) .to_string(PostgresQueryBuilder), - r#"INSERT INTO "glyph" ("aspect", "tokens") VALUES (3.1415, '{}')"# + r#"INSERT INTO "glyph" ("aspect", "tokens") VALUES (3.141592653589793, '{}')"# ); } diff --git a/tests/sqlite/query.rs b/tests/sqlite/query.rs index 53c491831..54a5008be 100644 --- a/tests/sqlite/query.rs +++ b/tests/sqlite/query.rs @@ -1119,7 +1119,9 @@ fn insert_4() { Query::insert() .into_table(Glyph::Table) .columns([Glyph::Image]) - .values_panic([chrono::NaiveDateTime::from_timestamp_opt(0, 0) + .values_panic([chrono::NaiveDate::from_ymd_opt(1970, 1, 1) + .unwrap() + .and_hms_opt(0, 0, 0) .unwrap() .into()]) .to_string(SqliteQueryBuilder),