diff --git a/diesel/src/expression/count.rs b/diesel/src/expression/count.rs index 0a8ea4d2dbc4..eed36a887cc0 100644 --- a/diesel/src/expression/count.rs +++ b/diesel/src/expression/count.rs @@ -1,6 +1,6 @@ use std::marker::PhantomData; -use super::functions::sql_function; +use super::functions::sql_function_v2; use super::{is_aggregate, AsExpression}; use super::{Expression, ValidGrouping}; use crate::backend::Backend; @@ -9,7 +9,7 @@ use crate::result::QueryResult; use crate::sql_types::{BigInt, DieselNumericOps, SingleValue, SqlType}; use crate::{AppearsOnTable, SelectableExpression}; -sql_function! { +sql_function_v2! { /// Creates a SQL `COUNT` expression /// /// As with most bare functions, this is not exported by default. You can import diff --git a/diesel/src/expression/functions/aggregate_folding.rs b/diesel/src/expression/functions/aggregate_folding.rs index fb8b9b2bd464..96c884ade9a2 100644 --- a/diesel/src/expression/functions/aggregate_folding.rs +++ b/diesel/src/expression/functions/aggregate_folding.rs @@ -1,7 +1,7 @@ -use crate::expression::functions::sql_function; +use crate::expression::functions::sql_function_v2; use crate::sql_types::Foldable; -sql_function! { +sql_function_v2! { /// Represents a SQL `SUM` function. This function can only take types which are /// Foldable. /// @@ -21,7 +21,7 @@ sql_function! { fn sum(expr: ST) -> ST::Sum; } -sql_function! { +sql_function_v2! { /// Represents a SQL `AVG` function. This function can only take types which are /// Foldable. /// diff --git a/diesel/src/expression/functions/aggregate_ordering.rs b/diesel/src/expression/functions/aggregate_ordering.rs index aa95e1d1a64f..1e09ea2b4fcd 100644 --- a/diesel/src/expression/functions/aggregate_ordering.rs +++ b/diesel/src/expression/functions/aggregate_ordering.rs @@ -1,7 +1,7 @@ use self::private::SqlOrdAggregate; -use crate::expression::functions::sql_function; +use crate::expression::functions::sql_function_v2; -sql_function! { +sql_function_v2! { /// Represents a SQL `MAX` function. This function can only take types which are /// ordered. /// @@ -20,7 +20,7 @@ sql_function! { fn max(expr: ST) -> ST::Ret; } -sql_function! { +sql_function_v2! { /// Represents a SQL `MIN` function. This function can only take types which are /// ordered. /// diff --git a/diesel/src/expression/functions/date_and_time.rs b/diesel/src/expression/functions/date_and_time.rs index 22d51a470cec..40a76648d569 100644 --- a/diesel/src/expression/functions/date_and_time.rs +++ b/diesel/src/expression/functions/date_and_time.rs @@ -1,6 +1,6 @@ use crate::backend::Backend; use crate::expression::coerce::Coerce; -use crate::expression::functions::sql_function; +use crate::expression::functions::sql_function_v2; use crate::expression::{AsExpression, Expression, ValidGrouping}; use crate::query_builder::*; use crate::result::QueryResult; @@ -27,7 +27,7 @@ impl_selectable_expression!(now); operator_allowed!(now, Add, add); operator_allowed!(now, Sub, sub); -sql_function! { +sql_function_v2! { /// Represents the SQL `DATE` function. The argument should be a Timestamp /// expression, and the return value will be an expression of type Date. /// diff --git a/diesel/src/expression/functions/helper_types.rs b/diesel/src/expression/functions/helper_types.rs index ff757c350447..4f6bd2be06ab 100644 --- a/diesel/src/expression/functions/helper_types.rs +++ b/diesel/src/expression/functions/helper_types.rs @@ -8,16 +8,16 @@ use crate::expression::operators; pub type not = operators::Not>; /// The return type of [`max(expr)`](crate::dsl::max()) -pub type max = super::aggregate_ordering::max::HelperType, Expr>; +pub type max = super::aggregate_ordering::max, Expr>; /// The return type of [`min(expr)`](crate::dsl::min()) -pub type min = super::aggregate_ordering::min::HelperType, Expr>; +pub type min = super::aggregate_ordering::min, Expr>; /// The return type of [`sum(expr)`](crate::dsl::sum()) -pub type sum = super::aggregate_folding::sum::HelperType, Expr>; +pub type sum = super::aggregate_folding::sum, Expr>; /// The return type of [`avg(expr)`](crate::dsl::avg()) -pub type avg = super::aggregate_folding::avg::HelperType, Expr>; +pub type avg = super::aggregate_folding::avg, Expr>; /// The return type of [`exists(expr)`](crate::dsl::exists()) pub type exists = crate::expression::exists::Exists; diff --git a/diesel/src/expression/functions/mod.rs b/diesel/src/expression/functions/mod.rs index f37261412495..44201b2e3b32 100644 --- a/diesel/src/expression/functions/mod.rs +++ b/diesel/src/expression/functions/mod.rs @@ -1,7 +1,7 @@ //! Helper macros to define custom sql functions #[doc(inline)] -pub use diesel_derives::sql_function_proc as sql_function; +pub use diesel_derives::{sql_function_proc as sql_function, sql_function_v2}; #[macro_export] #[doc(hidden)] @@ -73,7 +73,7 @@ macro_rules! no_arg_sql_function_body { /// function. #[deprecated( since = "2.0.0", - note = "Use `sql_function!` instead. See `CHANGELOG.md` for migration instructions" + note = "Use `sql_function_v2!` instead. See `CHANGELOG.md` for migration instructions" )] #[cfg(all(feature = "with-deprecated", not(feature = "without-deprecated")))] macro_rules! no_arg_sql_function { diff --git a/diesel/src/expression/mod.rs b/diesel/src/expression/mod.rs index f54d5244a470..c87d4a4f6f7a 100644 --- a/diesel/src/expression/mod.rs +++ b/diesel/src/expression/mod.rs @@ -73,7 +73,7 @@ pub(crate) mod dsl { pub use crate::pg::expression::dsl::*; /// The return type of [`count(expr)`](crate::dsl::count()) - pub type count = super::count::count::HelperType, Expr>; + pub type count = super::count::count, Expr>; /// The return type of [`count_star()`](crate::dsl::count_star()) pub type count_star = super::count::CountStar; @@ -82,7 +82,7 @@ pub(crate) mod dsl { pub type count_distinct = super::count::CountDistinct, Expr>; /// The return type of [`date(expr)`](crate::dsl::date()) - pub type date = super::functions::date_and_time::date::HelperType; + pub type date = super::functions::date_and_time::date; #[cfg(feature = "mysql_backend")] pub use crate::mysql::query_builder::DuplicatedKeys; diff --git a/diesel/src/lib.rs b/diesel/src/lib.rs index ef8f22404528..57cb87b59d4c 100644 --- a/diesel/src/lib.rs +++ b/diesel/src/lib.rs @@ -57,7 +57,7 @@ //! They live in [the `dsl` module](dsl). //! Diesel only supports a very small number of these functions. //! You can declare additional functions you want to use -//! with [the `sql_function!` macro][`sql_function!`]. +//! with [the `sql_function_v2!` macro][`sql_function_v2!`]. //! //! [`std::ops`]: //doc.rust-lang.org/stable/std/ops/index.html //! @@ -640,7 +640,7 @@ pub mod prelude { }; #[doc(inline)] - pub use crate::expression::functions::sql_function; + pub use crate::expression::functions::{sql_function, sql_function_v2}; #[doc(inline)] pub use crate::expression::SelectableHelper; diff --git a/diesel/src/pg/connection/mod.rs b/diesel/src/pg/connection/mod.rs index aa1bec8a55e7..b8b3a9424fe5 100644 --- a/diesel/src/pg/connection/mod.rs +++ b/diesel/src/pg/connection/mod.rs @@ -584,7 +584,7 @@ mod tests { assert_eq!(2, connection.statement_cache.len()); } - sql_function!(fn lower(x: VarChar) -> VarChar); + sql_function_v2!(fn lower(x: VarChar) -> VarChar); #[test] fn queries_with_identical_types_and_binds_but_different_sql_are_cached_separately() { diff --git a/diesel/src/pg/expression/functions.rs b/diesel/src/pg/expression/functions.rs index 254856268564..f91b20b0c4f9 100644 --- a/diesel/src/pg/expression/functions.rs +++ b/diesel/src/pg/expression/functions.rs @@ -1,61 +1,61 @@ //! PostgreSQL specific functions use super::expression_methods::InetOrCidr; -use crate::expression::functions::sql_function; +use crate::expression::functions::sql_function_v2; use crate::sql_types::*; -sql_function! { +sql_function_v2! { /// Creates an abbreviated display format as text. #[cfg(feature = "postgres_backend")] fn abbrev(addr: T) -> Text; } -sql_function! { +sql_function_v2! { /// Computes the broadcast address for the address's network. #[cfg(feature = "postgres_backend")] fn broadcast(addr: T) -> Inet; } -sql_function! { +sql_function_v2! { /// Returns the address's family: 4 for IPv4, 6 for IPv6. #[cfg(feature = "postgres_backend")] fn family(addr: T) -> Integer; } -sql_function! { +sql_function_v2! { /// Returns the IP address as text, ignoring the netmask. #[cfg(feature = "postgres_backend")] fn host(addr: T) -> Text; } -sql_function! { +sql_function_v2! { /// Computes the host mask for the address's network. #[cfg(feature = "postgres_backend")] fn hostmask(addr: T) -> Inet; } -sql_function! { +sql_function_v2! { /// Computes the smallest network that includes both of the given networks. #[cfg(feature = "postgres_backend")] fn inet_merge(a: T, b: U) -> Cidr; } -sql_function! { +sql_function_v2! { /// Tests whether the addresses belong to the same IP family. #[cfg(feature = "postgres_backend")] fn inet_same_family(a: T, b: U) -> Bool; } -sql_function! { +sql_function_v2! { /// Returns the netmask length in bits. #[cfg(feature = "postgres_backend")] fn masklen(addr: T) -> Integer; } -sql_function! { +sql_function_v2! { /// Computes the network mask for the address's network. #[cfg(feature = "postgres_backend")] fn netmask(addr: T) -> Inet; } -sql_function! { +sql_function_v2! { /// Returns the network part of the address, zeroing out whatever is to the right of the /// netmask. (This is equivalent to casting the value to cidr.) #[cfg(feature = "postgres_backend")] fn network(addr: T) -> Cidr; } -sql_function! { +sql_function_v2! { /// Sets the netmask length for an inet or cidr value. /// For inet, the address part does not changes. For cidr, address bits to the right of the new /// netmask are set to zero. diff --git a/diesel/src/pg/metadata_lookup.rs b/diesel/src/pg/metadata_lookup.rs index bf08a9d2706e..16aaf2f65076 100644 --- a/diesel/src/pg/metadata_lookup.rs +++ b/diesel/src/pg/metadata_lookup.rs @@ -214,4 +214,4 @@ table! { joinable!(pg_type -> pg_namespace(typnamespace)); allow_tables_to_appear_in_same_query!(pg_type, pg_namespace); -sql_function! { fn pg_my_temp_schema() -> Oid; } +sql_function_v2! { fn pg_my_temp_schema() -> Oid; } diff --git a/diesel/src/sqlite/connection/mod.rs b/diesel/src/sqlite/connection/mod.rs index 2549897d35ec..497cad817c45 100644 --- a/diesel/src/sqlite/connection/mod.rs +++ b/diesel/src/sqlite/connection/mod.rs @@ -634,12 +634,12 @@ mod tests { } use crate::sql_types::Text; - sql_function!(fn fun_case(x: Text) -> Text); + sql_function_v2!(fn fun_case(x: Text) -> Text); #[test] fn register_custom_function() { let connection = &mut SqliteConnection::establish(":memory:").unwrap(); - fun_case::register_impl(connection, |x: String| { + fun_case_internals::register_impl(connection, |x: String| { x.chars() .enumerate() .map(|(i, c)| { @@ -659,23 +659,23 @@ mod tests { assert_eq!("fOoBaR", mapped_string); } - sql_function!(fn my_add(x: Integer, y: Integer) -> Integer); + sql_function_v2!(fn my_add(x: Integer, y: Integer) -> Integer); #[test] fn register_multiarg_function() { let connection = &mut SqliteConnection::establish(":memory:").unwrap(); - my_add::register_impl(connection, |x: i32, y: i32| x + y).unwrap(); + my_add_internals::register_impl(connection, |x: i32, y: i32| x + y).unwrap(); let added = crate::select(my_add(1, 2)).get_result::(connection); assert_eq!(Ok(3), added); } - sql_function!(fn answer() -> Integer); + sql_function_v2!(fn answer() -> Integer); #[test] fn register_noarg_function() { let connection = &mut SqliteConnection::establish(":memory:").unwrap(); - answer::register_impl(connection, || 42).unwrap(); + answer_internals::register_impl(connection, || 42).unwrap(); let answer = crate::select(answer()).get_result::(connection); assert_eq!(Ok(42), answer); @@ -684,19 +684,19 @@ mod tests { #[test] fn register_nondeterministic_noarg_function() { let connection = &mut SqliteConnection::establish(":memory:").unwrap(); - answer::register_nondeterministic_impl(connection, || 42).unwrap(); + answer_internals::register_nondeterministic_impl(connection, || 42).unwrap(); let answer = crate::select(answer()).get_result::(connection); assert_eq!(Ok(42), answer); } - sql_function!(fn add_counter(x: Integer) -> Integer); + sql_function_v2!(fn add_counter(x: Integer) -> Integer); #[test] fn register_nondeterministic_function() { let connection = &mut SqliteConnection::establish(":memory:").unwrap(); let mut y = 0; - add_counter::register_nondeterministic_impl(connection, move |x: i32| { + add_counter_internals::register_nondeterministic_impl(connection, move |x: i32| { y += 1; x + y }) @@ -709,7 +709,7 @@ mod tests { use crate::sqlite::SqliteAggregateFunction; - sql_function! { + sql_function_v2! { #[aggregate] fn my_sum(expr: Integer) -> Integer; } @@ -752,7 +752,7 @@ mod tests { .execute(connection) .unwrap(); - my_sum::register_impl::(connection).unwrap(); + my_sum_internals::register_impl::(connection).unwrap(); let result = my_sum_example .select(my_sum(value)) @@ -771,7 +771,7 @@ mod tests { .execute(connection) .unwrap(); - my_sum::register_impl::(connection).unwrap(); + my_sum_internals::register_impl::(connection).unwrap(); let result = my_sum_example .select(my_sum(value)) @@ -779,7 +779,7 @@ mod tests { assert_eq!(Ok(0), result); } - sql_function! { + sql_function_v2! { #[aggregate] fn range_max(expr1: Integer, expr2: Integer, expr3: Integer) -> Nullable; } @@ -843,7 +843,7 @@ mod tests { .execute(connection) .unwrap(); - range_max::register_impl::, _, _, _>(connection).unwrap(); + range_max_internals::register_impl::, _, _, _>(connection).unwrap(); let result = range_max_example .select(range_max(value1, value2, value3)) .get_result::>(connection) diff --git a/diesel/src/sqlite/mod.rs b/diesel/src/sqlite/mod.rs index 6a9fbbe9fc58..40bd37f7da26 100644 --- a/diesel/src/sqlite/mod.rs +++ b/diesel/src/sqlite/mod.rs @@ -21,9 +21,9 @@ pub use self::query_builder::SqliteQueryBuilder; /// Trait for the implementation of a SQLite aggregate function /// -/// This trait is to be used in conjunction with the `sql_function!` +/// This trait is to be used in conjunction with the `sql_function_v2!` /// macro for defining a custom SQLite aggregate function. See -/// the documentation [there](super::prelude::sql_function!) for details. +/// the documentation [there](super::prelude::sql_function_v2!) for details. pub trait SqliteAggregateFunction: Default { /// The result type of the SQLite aggregate function type Output; diff --git a/diesel/src/sqlite/types/date_and_time/chrono.rs b/diesel/src/sqlite/types/date_and_time/chrono.rs index 3877253a8744..d76948d8a26c 100644 --- a/diesel/src/sqlite/types/date_and_time/chrono.rs +++ b/diesel/src/sqlite/types/date_and_time/chrono.rs @@ -249,9 +249,9 @@ mod tests { use crate::sql_types::{Text, Time, Timestamp, TimestamptzSqlite}; use crate::test_helpers::connection; - sql_function!(fn datetime(x: Text) -> Timestamp); - sql_function!(fn time(x: Text) -> Time); - sql_function!(fn date(x: Text) -> Date); + sql_function_v2!(fn datetime(x: Text) -> Timestamp); + sql_function_v2!(fn time(x: Text) -> Time); + sql_function_v2!(fn date(x: Text) -> Date); #[test] fn unix_epoch_encodes_correctly() { diff --git a/diesel/src/sqlite/types/date_and_time/time.rs b/diesel/src/sqlite/types/date_and_time/time.rs index 3995f39c459e..13c66c24544a 100644 --- a/diesel/src/sqlite/types/date_and_time/time.rs +++ b/diesel/src/sqlite/types/date_and_time/time.rs @@ -275,9 +275,9 @@ mod tests { use crate::sql_types::{Text, Time, Timestamp, TimestamptzSqlite}; use crate::test_helpers::connection; - sql_function!(fn datetime(x: Text) -> Timestamp); - sql_function!(fn time(x: Text) -> Time); - sql_function!(fn date(x: Text) -> Date); + sql_function_v2!(fn datetime(x: Text) -> Timestamp); + sql_function_v2!(fn time(x: Text) -> Time); + sql_function_v2!(fn date(x: Text) -> Date); #[test] fn unix_epoch_encodes_correctly() { diff --git a/diesel_cli/src/infer_schema_internals/information_schema.rs b/diesel_cli/src/infer_schema_internals/information_schema.rs index 6c762de91db7..47669edf66f1 100644 --- a/diesel_cli/src/infer_schema_internals/information_schema.rs +++ b/diesel_cli/src/infer_schema_internals/information_schema.rs @@ -31,7 +31,7 @@ impl DefaultSchema for Pg { } #[cfg(feature = "mysql")] -sql_function!(fn database() -> VarChar); +sql_function_v2!(fn database() -> VarChar); #[cfg(feature = "mysql")] impl DefaultSchema for Mysql { diff --git a/diesel_cli/src/infer_schema_internals/mysql.rs b/diesel_cli/src/infer_schema_internals/mysql.rs index 40021246b120..586d71c25422 100644 --- a/diesel_cli/src/infer_schema_internals/mysql.rs +++ b/diesel_cli/src/infer_schema_internals/mysql.rs @@ -10,7 +10,7 @@ use super::information_schema::DefaultSchema; use super::table_data::TableName; use crate::print_schema::ColumnSorting; -diesel::sql_function! { +diesel::sql_function_v2! { #[sql_name = "NULLIF"] fn null_if_text(lhs: sql_types::Text, rhs: sql_types::Text) -> sql_types::Nullable } diff --git a/diesel_cli/src/infer_schema_internals/pg.rs b/diesel_cli/src/infer_schema_internals/pg.rs index 15d48f7feebb..94aded110dba 100644 --- a/diesel_cli/src/infer_schema_internals/pg.rs +++ b/diesel_cli/src/infer_schema_internals/pg.rs @@ -70,7 +70,7 @@ fn regclass(table: &TableName) -> Regclass> { )) } -diesel::sql_function!(fn col_description(table: sql_types::Oid, column_number: sql_types::BigInt) -> sql_types::Nullable); +diesel::sql_function_v2!(fn col_description(table: sql_types::Oid, column_number: sql_types::BigInt) -> sql_types::Nullable); pub fn get_table_data( conn: &mut PgConnection, @@ -139,7 +139,7 @@ where } } -sql_function!(fn obj_description(oid: sql_types::Oid, catalog: sql_types::Text) -> Nullable); +sql_function_v2!(fn obj_description(oid: sql_types::Oid, catalog: sql_types::Text) -> Nullable); pub fn get_table_comment( conn: &mut PgConnection, @@ -166,7 +166,7 @@ mod information_schema { } } -sql_function! { +sql_function_v2! { #[aggregate] fn array_agg(input: diesel::sql_types::Text) -> diesel::sql_types::Array; } diff --git a/diesel_compile_tests/tests/fail/cannot_mix_aggregate_and_non_aggregate_selects.rs b/diesel_compile_tests/tests/fail/cannot_mix_aggregate_and_non_aggregate_selects.rs index d44fe0069691..ac42c700c7d3 100644 --- a/diesel_compile_tests/tests/fail/cannot_mix_aggregate_and_non_aggregate_selects.rs +++ b/diesel_compile_tests/tests/fail/cannot_mix_aggregate_and_non_aggregate_selects.rs @@ -11,7 +11,7 @@ table! { } } -sql_function!(fn f(x: Nullable, y: Nullable) -> Nullable); +sql_function_v2!(fn f(x: Nullable, y: Nullable) -> Nullable); fn main() { use self::users::dsl::*; diff --git a/diesel_compile_tests/tests/fail/cannot_mix_aggregate_and_non_aggregate_selects.stderr b/diesel_compile_tests/tests/fail/cannot_mix_aggregate_and_non_aggregate_selects.stderr index dc7b430a10bd..100a091debae 100644 --- a/diesel_compile_tests/tests/fail/cannot_mix_aggregate_and_non_aggregate_selects.stderr +++ b/diesel_compile_tests/tests/fail/cannot_mix_aggregate_and_non_aggregate_selects.stderr @@ -34,9 +34,9 @@ error[E0277]: the trait bound `diesel::expression::is_aggregate::No: MixedAggreg note: required for `__Derived, nullable_int_col>>` to implement `ValidGrouping<()>` --> tests/fail/cannot_mix_aggregate_and_non_aggregate_selects.rs:14:1 | -14 | sql_function!(fn f(x: Nullable, y: Nullable) -> Nullable); +14 | sql_function_v2!(fn f(x: Nullable, y: Nullable) -> Nullable); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro = note: 1 redundant requirement hidden = note: required for `f, nullable_int_col>>` to implement `ValidGrouping<()>` = note: required for `SelectStatement>` to implement `SelectDsl, columns::nullable_int_col>>>` - = note: this error originates in the macro `sql_function` which comes from the expansion of the derive macro `ValidGrouping` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `sql_function_v2` which comes from the expansion of the derive macro `ValidGrouping` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/diesel_compile_tests/tests/fail/pg_on_conflict_requires_valid_conflict_target.rs b/diesel_compile_tests/tests/fail/pg_on_conflict_requires_valid_conflict_target.rs index 6f4816a2695b..88043f33ade9 100644 --- a/diesel_compile_tests/tests/fail/pg_on_conflict_requires_valid_conflict_target.rs +++ b/diesel_compile_tests/tests/fail/pg_on_conflict_requires_valid_conflict_target.rs @@ -20,7 +20,7 @@ table! { #[diesel(table_name = users)] pub struct NewUser(#[diesel(column_name = name)] &'static str); -sql_function!(fn lower(x: diesel::sql_types::Text) -> diesel::sql_types::Text); +sql_function_v2!(fn lower(x: diesel::sql_types::Text) -> diesel::sql_types::Text); fn main() { use self::users::dsl::*; diff --git a/diesel_compile_tests/tests/fail/pg_specific_expressions_cant_be_used_in_a_sqlite_query.rs b/diesel_compile_tests/tests/fail/pg_specific_expressions_cant_be_used_in_a_sqlite_query.rs index 1d7945e845f9..82215c89e738 100644 --- a/diesel_compile_tests/tests/fail/pg_specific_expressions_cant_be_used_in_a_sqlite_query.rs +++ b/diesel_compile_tests/tests/fail/pg_specific_expressions_cant_be_used_in_a_sqlite_query.rs @@ -12,7 +12,7 @@ table! { } } -sql_function!(fn lower(x: VarChar) -> VarChar); +sql_function_v2!(fn lower(x: VarChar) -> VarChar); #[derive(Insertable)] #[diesel(table_name = users)] @@ -23,13 +23,20 @@ fn main() { use self::users::dsl::*; let mut connection = SqliteConnection::establish(":memory:").unwrap(); - users.select(id).filter(name.eq(any(Vec::::new()))) + users + .select(id) + .filter(name.eq(any(Vec::::new()))) .load::(&mut connection); - users.select(id).filter(name.is_not_distinct_from("Sean")) + users + .select(id) + .filter(name.is_not_distinct_from("Sean")) .load::(&mut connection); - users.select(id).filter(now.eq(now.at_time_zone("UTC"))) + users + .select(id) + .filter(now.eq(now.at_time_zone("UTC"))) .load::(&mut connection); - insert_into(users).values(&NewUser("Sean")) + insert_into(users) + .values(&NewUser("Sean")) .on_conflict(on_constraint("name")) .execute(&mut connection); } diff --git a/diesel_compile_tests/tests/fail/right_side_of_left_join_requires_nullable.rs b/diesel_compile_tests/tests/fail/right_side_of_left_join_requires_nullable.rs index c62f19081a47..71934d2dd4cd 100644 --- a/diesel_compile_tests/tests/fail/right_side_of_left_join_requires_nullable.rs +++ b/diesel_compile_tests/tests/fail/right_side_of_left_join_requires_nullable.rs @@ -30,7 +30,7 @@ table! { joinable!(posts -> users (user_id)); joinable!(pets -> users (user_id)); allow_tables_to_appear_in_same_query!(posts, users, pets); -sql_function!(fn lower(x: Text) -> Text); +sql_function_v2!(fn lower(x: Text) -> Text); fn main() {} diff --git a/diesel_compile_tests/tests/fail/right_side_of_left_join_requires_nullable.stderr b/diesel_compile_tests/tests/fail/right_side_of_left_join_requires_nullable.stderr index 6af0978c0633..d7137daa624e 100644 --- a/diesel_compile_tests/tests/fail/right_side_of_left_join_requires_nullable.stderr +++ b/diesel_compile_tests/tests/fail/right_side_of_left_join_requires_nullable.stderr @@ -88,9 +88,9 @@ error[E0271]: type mismatch resolving ` as Expression>::SqlType note: required by a bound in `lower` --> tests/fail/right_side_of_left_join_requires_nullable.rs:33:1 | -33 | sql_function!(fn lower(x: Text) -> Text); +33 | sql_function_v2!(fn lower(x: Text) -> Text); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `lower` - = note: this error originates in the macro `sql_function` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `sql_function_v2` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0271]: type mismatch resolving ` as Expression>::SqlType == Text` --> tests/fail/right_side_of_left_join_requires_nullable.rs:49:25 @@ -192,9 +192,9 @@ error[E0271]: type mismatch resolving ` as Expression>::SqlType note: required by a bound in `lower` --> tests/fail/right_side_of_left_join_requires_nullable.rs:33:1 | -33 | sql_function!(fn lower(x: Text) -> Text); +33 | sql_function_v2!(fn lower(x: Text) -> Text); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `lower` - = note: this error originates in the macro `sql_function` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `sql_function_v2` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0271]: type mismatch resolving ` as Expression>::SqlType == Text` --> tests/fail/right_side_of_left_join_requires_nullable.rs:66:25 @@ -296,9 +296,9 @@ error[E0271]: type mismatch resolving ` as Expression>::SqlType note: required by a bound in `lower` --> tests/fail/right_side_of_left_join_requires_nullable.rs:33:1 | -33 | sql_function!(fn lower(x: Text) -> Text); +33 | sql_function_v2!(fn lower(x: Text) -> Text); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `lower` - = note: this error originates in the macro `sql_function` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `sql_function_v2` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0271]: type mismatch resolving ` as Expression>::SqlType == Text` --> tests/fail/right_side_of_left_join_requires_nullable.rs:83:25 @@ -400,9 +400,9 @@ error[E0271]: type mismatch resolving ` as Expression>::SqlType note: required by a bound in `lower` --> tests/fail/right_side_of_left_join_requires_nullable.rs:33:1 | -33 | sql_function!(fn lower(x: Text) -> Text); +33 | sql_function_v2!(fn lower(x: Text) -> Text); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `lower` - = note: this error originates in the macro `sql_function` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `sql_function_v2` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0271]: type mismatch resolving ` as Expression>::SqlType == Text` --> tests/fail/right_side_of_left_join_requires_nullable.rs:98:25 @@ -504,9 +504,9 @@ error[E0271]: type mismatch resolving ` as Expression>::SqlType note: required by a bound in `lower` --> tests/fail/right_side_of_left_join_requires_nullable.rs:33:1 | -33 | sql_function!(fn lower(x: Text) -> Text); +33 | sql_function_v2!(fn lower(x: Text) -> Text); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `lower` - = note: this error originates in the macro `sql_function` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `sql_function_v2` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0271]: type mismatch resolving ` as Expression>::SqlType == Text` --> tests/fail/right_side_of_left_join_requires_nullable.rs:113:25 diff --git a/diesel_compile_tests/tests/fail/user_defined_functions_follow_same_selection_rules.rs b/diesel_compile_tests/tests/fail/user_defined_functions_follow_same_selection_rules.rs index 88a40720aee3..dc11cc310e8a 100644 --- a/diesel_compile_tests/tests/fail/user_defined_functions_follow_same_selection_rules.rs +++ b/diesel_compile_tests/tests/fail/user_defined_functions_follow_same_selection_rules.rs @@ -1,7 +1,7 @@ extern crate diesel; -use diesel::*; use diesel::sql_types::*; +use diesel::*; table! { users { @@ -23,17 +23,18 @@ struct User { name: String, } -sql_function!(fn foo(x: Integer) -> Integer); -sql_function!(fn bar(x: VarChar) -> VarChar); +sql_function_v2!(fn foo(x: Integer) -> Integer); +sql_function_v2!(fn bar(x: VarChar) -> VarChar); fn main() { - use self::users::name; use self::posts::title; + use self::users::name; let mut conn = PgConnection::establish("").unwrap(); let _ = users::table.filter(name.eq(foo(1))); - let _ = users::table.filter(name.eq(bar(title))) + let _ = users::table + .filter(name.eq(bar(title))) .load::(&mut conn); } diff --git a/diesel_derives/src/lib.rs b/diesel_derives/src/lib.rs index b1dceb5f86fd..85dd45bd8de8 100644 --- a/diesel_derives/src/lib.rs +++ b/diesel_derives/src/lib.rs @@ -1013,46 +1013,17 @@ pub fn derive_valid_grouping(input: TokenStream) -> TokenStream { /// function. For example, this invocation: /// /// ```ignore -/// sql_function!(fn lower(x: Text) -> Text); +/// sql_function_v2!(fn lower(x: Text) -> Text); /// ``` /// /// will generate this code: /// /// ```ignore -/// pub fn lower(x: X) -> lower::HelperType { +/// pub fn lower(x: X) -> lower { /// ... /// } /// -/// pub(crate) mod lower { -/// pub type HelperType = ...; -/// } -/// ``` -/// -/// If you are using this macro for part of a library, where the function is -/// part of your public API, it is highly recommended that you re-export this -/// helper type with the same name as your function. This is the standard -/// structure: -/// -/// ```ignore -/// pub mod functions { -/// use super::types::*; -/// use diesel::sql_types::*; -/// -/// sql_function! { -/// /// Represents the Pg `LENGTH` function used with `tsvector`s. -/// fn length(x: TsVector) -> Integer; -/// } -/// } -/// -/// pub mod helper_types { -/// /// The return type of `length(expr)` -/// pub type Length = functions::length::HelperType; -/// } -/// -/// pub mod dsl { -/// pub use functions::*; -/// pub use helper_types::*; -/// } +/// pub type lower = ...; /// ``` /// /// Most attributes given to this macro will be put on the generated function @@ -1068,7 +1039,7 @@ pub fn derive_valid_grouping(input: TokenStream) -> TokenStream { /// # /// use diesel::sql_types::Text; /// -/// sql_function! { +/// sql_function_v2! { /// /// Represents the `canon_crate_name` SQL function, created in /// /// migration .... /// fn canon_crate_name(a: Text) -> Text; @@ -1106,7 +1077,7 @@ pub fn derive_valid_grouping(input: TokenStream) -> TokenStream { /// # /// use diesel::sql_types::Foldable; /// -/// sql_function! { +/// sql_function_v2! { /// #[aggregate] /// #[sql_name = "SUM"] /// fn sum(expr: ST) -> ST::Sum; @@ -1121,7 +1092,7 @@ pub fn derive_valid_grouping(input: TokenStream) -> TokenStream { /// # SQL Functions without Arguments /// /// A common example is ordering a query using the `RANDOM()` sql function, -/// which can be implemented using `sql_function!` like this: +/// which can be implemented using `sql_function_v2!` like this: /// /// ```rust /// # extern crate diesel; @@ -1129,7 +1100,7 @@ pub fn derive_valid_grouping(input: TokenStream) -> TokenStream { /// # /// # table! { crates { id -> Integer, name -> VarChar, } } /// # -/// sql_function!(fn random() -> Text); +/// sql_function_v2!(fn random() -> Text); /// /// # fn main() { /// # use self::crates::dsl::*; @@ -1142,8 +1113,8 @@ pub fn derive_valid_grouping(input: TokenStream) -> TokenStream { /// On most backends, the implementation of the function is defined in a /// migration using `CREATE FUNCTION`. On SQLite, the function is implemented in /// Rust instead. You must call `register_impl` or -/// `register_nondeterministic_impl` with every connection before you can use -/// the function. +/// `register_nondeterministic_impl` (in the generated function's `_internals` +/// module) with every connection before you can use the function. /// /// These functions will only be generated if the `sqlite` feature is enabled, /// and the function is not generic. @@ -1163,13 +1134,13 @@ pub fn derive_valid_grouping(input: TokenStream) -> TokenStream { /// # } /// # /// use diesel::sql_types::{Integer, Double}; -/// sql_function!(fn add_mul(x: Integer, y: Integer, z: Double) -> Double); +/// sql_function_v2!(fn add_mul(x: Integer, y: Integer, z: Double) -> Double); /// /// # #[cfg(feature = "sqlite")] /// # fn run_test() -> Result<(), Box> { /// let connection = &mut SqliteConnection::establish(":memory:")?; /// -/// add_mul::register_impl(connection, |x: i32, y: i32, z: f64| { +/// add_mul_internals::register_impl(connection, |x: i32, y: i32, z: f64| { /// (x + y) as f64 * z /// })?; /// @@ -1191,8 +1162,8 @@ pub fn derive_valid_grouping(input: TokenStream) -> TokenStream { /// ## Custom Aggregate Functions /// /// Custom aggregate functions can be created in SQLite by adding an `#[aggregate]` -/// attribute inside `sql_function`. `register_impl` needs to be called on -/// the generated function with a type implementing the +/// attribute inside `sql_function_v2`. `register_impl` (in the generated function's `_internals` +/// module) needs to be called with a type implementing the /// [SqliteAggregateFunction](../diesel/sqlite/trait.SqliteAggregateFunction.html) /// trait as a type parameter as shown in the examples below. /// @@ -1212,7 +1183,7 @@ pub fn derive_valid_grouping(input: TokenStream) -> TokenStream { /// # #[cfg(feature = "sqlite")] /// use diesel::sqlite::SqliteAggregateFunction; /// -/// sql_function! { +/// sql_function_v2! { /// #[aggregate] /// fn my_sum(x: Integer) -> Integer; /// } @@ -1250,7 +1221,7 @@ pub fn derive_valid_grouping(input: TokenStream) -> TokenStream { /// # .execute(connection) /// # .unwrap(); /// -/// my_sum::register_impl::(connection)?; +/// my_sum_internals::register_impl::(connection)?; /// /// let total_score = players.select(my_sum(score)) /// .get_result::(connection)?; @@ -1280,7 +1251,7 @@ pub fn derive_valid_grouping(input: TokenStream) -> TokenStream { /// # #[cfg(feature = "sqlite")] /// use diesel::sqlite::SqliteAggregateFunction; /// -/// sql_function! { +/// sql_function_v2! { /// #[aggregate] /// fn range_max(x0: Float, x1: Float) -> Nullable; /// } @@ -1330,7 +1301,7 @@ pub fn derive_valid_grouping(input: TokenStream) -> TokenStream { /// # .execute(connection) /// # .unwrap(); /// -/// range_max::register_impl::, _, _>(connection)?; +/// range_max_internals::register_impl::, _, _>(connection)?; /// /// let result = student_avgs.select(range_max(s1_avg, s2_avg)) /// .get_result::>(connection)?; @@ -1344,8 +1315,41 @@ pub fn derive_valid_grouping(input: TokenStream) -> TokenStream { /// } /// ``` #[proc_macro] +pub fn sql_function_v2(input: TokenStream) -> TokenStream { + sql_function::expand(parse_macro_input!(input), false).into() +} + +/// A legacy version of [`sql_function_v2!`]. +/// +/// The difference is that it makes the helper type available in a module named the exact same as +/// the function: +/// +/// ```ignore +/// sql_function!(fn lower(x: Text) -> Text); +/// ``` +/// +/// will generate this code: +/// +/// ```ignore +/// pub fn lower(x: X) -> lower::HelperType { +/// ... +/// } +/// +/// pub(crate) mod lower { +/// pub type HelperType = ...; +/// } +/// ``` +/// +/// This turned out to be an issue for the support of the `auto_type` feature, which is why +/// [`sql_function_v2!`] was introduced (and why this is deprecated). +/// +/// SQL functions declared with this version of the macro will not be usable with `#[auto_type]` +/// or `Selectable` `select_expression` type inference. + +#[deprecated = "Use [`sql_function_v2`] instead"] +#[proc_macro] pub fn sql_function_proc(input: TokenStream) -> TokenStream { - sql_function::expand(parse_macro_input!(input)).into() + sql_function::expand(parse_macro_input!(input), true).into() } /// This is an internal diesel macro that diff --git a/diesel_derives/src/sql_function.rs b/diesel_derives/src/sql_function.rs index 9a9ed90fe59b..ee93407ed855 100644 --- a/diesel_derives/src/sql_function.rs +++ b/diesel_derives/src/sql_function.rs @@ -8,7 +8,7 @@ use syn::{ PathArguments, Token, Type, }; -pub(crate) fn expand(input: SqlFunctionDecl) -> TokenStream { +pub(crate) fn expand(input: SqlFunctionDecl, legacy_helper_type_and_module: bool) -> TokenStream { let SqlFunctionDecl { mut attributes, fn_token, @@ -94,6 +94,8 @@ pub(crate) fn expand(input: SqlFunctionDecl) -> TokenStream { numeric_derive = Some(quote!(#[derive(diesel::sql_types::DieselNumericOps)])); } + let helper_type_doc = format!("The return type of [`{fn_name}()`](super::fn_name)"); + let args_iter = args.iter(); let mut tokens = quote! { use diesel::{self, QueryResult}; @@ -109,6 +111,7 @@ pub(crate) fn expand(input: SqlFunctionDecl) -> TokenStream { #(pub(in super) #type_args: ::std::marker::PhantomData<#type_args>,)* } + #[doc = #helper_type_doc] pub type HelperType #ty_generics = #fn_name < #(#type_args,)* #(<#arg_name as AsExpression<#arg_type>>::Expression,)* @@ -391,23 +394,44 @@ pub(crate) fn expand(input: SqlFunctionDecl) -> TokenStream { let args_iter = args.iter(); + let (outside_of_module_helper_type, return_type_path, internals_module_name) = + if legacy_helper_type_and_module { + (None, quote! { #fn_name }, fn_name.clone()) + } else { + let internals_module_name = Ident::new(&format!("{fn_name}_internals"), fn_name.span()); + ( + Some(quote! { + #[allow(non_camel_case_types, non_snake_case)] + #[doc = #helper_type_doc] + pub type #fn_name #ty_generics = #internals_module_name::#fn_name < + #(#type_args,)* + #(<#arg_name as ::diesel::expression::AsExpression<#arg_type>>::Expression,)* + >; + }), + quote! { #fn_name }, + internals_module_name, + ) + }; + quote! { #(#attributes)* #[allow(non_camel_case_types)] pub #fn_token #fn_name #impl_generics (#(#args_iter,)*) - -> #fn_name::HelperType #ty_generics + -> #return_type_path #ty_generics #where_clause #(#arg_name: ::diesel::expression::AsExpression<#arg_type>,)* { - #fn_name::#fn_name { + #internals_module_name::#fn_name { #(#arg_struct_assign,)* #(#type_args: ::std::marker::PhantomData,)* } } + #outside_of_module_helper_type + #[doc(hidden)] #[allow(non_camel_case_types, non_snake_case, unused_imports)] - pub(crate) mod #fn_name { + pub(crate) mod #internals_module_name { #tokens } } diff --git a/diesel_tests/tests/annotations.rs b/diesel_tests/tests/annotations.rs index 7eb2caebc67b..a2d9f4a2ac93 100644 --- a/diesel_tests/tests/annotations.rs +++ b/diesel_tests/tests/annotations.rs @@ -286,7 +286,7 @@ fn derive_insertable_with_option_for_not_null_field_with_default() { assert_eq!(Some(&User::new(123, "Bob")), bob); } -sql_function!(fn nextval(a: Text) -> Integer); +sql_function_v2!(fn nextval(a: Text) -> Integer); #[test] #[cfg(feature = "postgres")] @@ -294,7 +294,7 @@ fn derive_insertable_with_field_that_cannot_convert_expression_to_nullable() { #[derive(Insertable)] #[diesel(table_name = users)] struct NewUser { - id: nextval::HelperType<&'static str>, + id: nextval<&'static str>, name: &'static str, } diff --git a/diesel_tests/tests/expressions/mod.rs b/diesel_tests/tests/expressions/mod.rs index 58a96053bb7c..f8ccf167b7d0 100644 --- a/diesel_tests/tests/expressions/mod.rs +++ b/diesel_tests/tests/expressions/mod.rs @@ -219,7 +219,7 @@ fn test_min() { assert_eq!(Ok(None::), source.first(connection)); } -sql_function!(fn coalesce(x: sql_types::Nullable, y: sql_types::VarChar) -> sql_types::VarChar); +sql_function_v2!(fn coalesce(x: sql_types::Nullable, y: sql_types::VarChar) -> sql_types::VarChar); #[test] fn function_with_multiple_arguments() { @@ -444,7 +444,7 @@ fn test_arrays_a() { #[cfg(feature = "postgres")] use diesel::sql_types::{Array, Int4}; #[cfg(feature = "postgres")] -sql_function!(fn unnest(a: Array) -> Int4); +sql_function_v2!(fn unnest(a: Array) -> Int4); #[test] #[cfg(feature = "postgres")] diff --git a/diesel_tests/tests/filter.rs b/diesel_tests/tests/filter.rs index 3d99733ebb86..e42c07dc1a44 100644 --- a/diesel_tests/tests/filter.rs +++ b/diesel_tests/tests/filter.rs @@ -412,7 +412,7 @@ fn not_affects_arguments_passed_when_they_contain_higher_operator_precedence() { } use diesel::sql_types::VarChar; -sql_function!(fn lower(x: VarChar) -> VarChar); +sql_function_v2!(fn lower(x: VarChar) -> VarChar); #[test] fn filter_by_boxed_predicate() { diff --git a/diesel_tests/tests/joins.rs b/diesel_tests/tests/joins.rs index bc4a447c480d..66a63b846753 100644 --- a/diesel_tests/tests/joins.rs +++ b/diesel_tests/tests/joins.rs @@ -358,7 +358,7 @@ fn select_then_join() { } use diesel::sql_types::Text; -sql_function!(fn lower(x: Text) -> Text); +sql_function_v2!(fn lower(x: Text) -> Text); #[test] fn selecting_complex_expression_from_right_side_of_left_join() { diff --git a/diesel_tests/tests/macros.rs b/diesel_tests/tests/macros.rs index e5727b8d47aa..673d48d8c3bb 100644 --- a/diesel_tests/tests/macros.rs +++ b/diesel_tests/tests/macros.rs @@ -7,7 +7,7 @@ use crate::schema::*; use diesel::sql_types::{BigInt, VarChar}; use diesel::*; -sql_function!(fn my_lower(x: VarChar) -> VarChar); +sql_function_v2!(fn my_lower(x: VarChar) -> VarChar); #[test] fn test_sql_function() { @@ -40,8 +40,8 @@ fn test_sql_function() { ); } -sql_function!(fn setval(x: VarChar, y: BigInt)); -sql_function!(fn currval(x: VarChar) -> BigInt); +sql_function_v2!(fn setval(x: VarChar, y: BigInt)); +sql_function_v2!(fn currval(x: VarChar) -> BigInt); #[test] fn sql_function_without_return_type() { diff --git a/diesel_tests/tests/schema/mod.rs b/diesel_tests/tests/schema/mod.rs index 7aad34912c19..76c22ce9b8ed 100644 --- a/diesel_tests/tests/schema/mod.rs +++ b/diesel_tests/tests/schema/mod.rs @@ -318,7 +318,7 @@ pub fn drop_table_cascade(connection: &mut TestConnection, table: &str) { .unwrap(); } -sql_function!(fn nextval(a: sql_types::VarChar) -> sql_types::BigInt); +sql_function_v2!(fn nextval(a: sql_types::VarChar) -> sql_types::BigInt); pub fn connection_with_sean_and_tess_in_users_table() -> TestConnection { let mut connection = connection(); diff --git a/guide_drafts/migration_guide.md b/guide_drafts/migration_guide.md index 591c0354777d..b2db9c63a5c2 100644 --- a/guide_drafts/migration_guide.md +++ b/guide_drafts/migration_guide.md @@ -32,7 +32,7 @@ by the following changes: * [Changed `FromSql` implementations](#2-0-0-from-sql) `no_arg_sql_function!` macro is now pending deprecation. -Users of the macro are advised to consider `sql_function!` macro. +Users of the macro are advised to consider `sql_function_v2!` macro. * [Deprecated usage of `no_arg_sql_function!` macro](#2-0-0-no_arg_sql_function) @@ -188,9 +188,9 @@ impl FromSql for YourType { ## `no_arg_sql_function` -The `no_arg_sql_function` was deprecated without direct replacement. At the same time the -`sql_function!` macro gained support for sql functions without argument. This support generates slightly -different code. Instead of representing the sql function as zero sized struct, `sql_function!` will generate an ordinary function call without arguments. This requires changing any usage of the generated dsl. This change +The `no_arg_sql_function` was deprecated without direct replacement. However the +`sql_function_v2!` macro gained support for sql functions without argument. This support generates slightly +different code. Instead of representing the sql function as zero sized struct, `sql_function_v2!` will generate an ordinary function call without arguments. This requires changing any usage of the generated dsl. This change affects all of the usages of the `no_arg_sql_function!` in third party crates. ```diff @@ -198,7 +198,7 @@ affects all of the usages of the `no_arg_sql_function!` in third party crates. - - diesel::select(now) -+ sql_function!{ ++ sql_function_v2!{ + /// Represents the SQL NOW() function + fn now() -> sql_types::Timestamp; + }