diff --git a/sqlx-core/src/encode.rs b/sqlx-core/src/encode.rs index 15f48a6086..51a1becfc3 100644 --- a/sqlx-core/src/encode.rs +++ b/sqlx-core/src/encode.rs @@ -2,6 +2,7 @@ use std::borrow::Cow; use std::mem; +use std::rc::Rc; use std::sync::Arc; use crate::database::Database; @@ -216,3 +217,31 @@ where (**self).size_hint() } } + +impl<'q, T, DB: Database> Encode<'q, DB> for Rc +where + T: Encode<'q, DB>, +{ + #[inline] + fn encode(self, buf: &mut ::ArgumentBuffer<'q>) -> Result { + >::encode_by_ref(self.as_ref(), buf) + } + + #[inline] + fn encode_by_ref( + &self, + buf: &mut ::ArgumentBuffer<'q>, + ) -> Result { + <&T as Encode>::encode(self, buf) + } + + #[inline] + fn produces(&self) -> Option { + (**self).produces() + } + + #[inline] + fn size_hint(&self) -> usize { + (**self).size_hint() + } +} diff --git a/sqlx-core/src/types/mod.rs b/sqlx-core/src/types/mod.rs index 1bc6aacd32..fd08b51bc1 100644 --- a/sqlx-core/src/types/mod.rs +++ b/sqlx-core/src/types/mod.rs @@ -17,7 +17,7 @@ //! To represent nullable SQL types, `Option` is supported where `T` implements `Type`. //! An `Option` represents a potentially `NULL` value from SQL. -use std::{borrow::Cow, sync::Arc}; +use std::{borrow::Cow, rc::Rc, sync::Arc}; use crate::database::Database; use crate::type_info::TypeInfo; @@ -278,3 +278,13 @@ impl, DB: Database> Type for Box { ty.is_null() || >::compatible(ty) } } + +impl, DB: Database> Type for Rc { + fn type_info() -> DB::TypeInfo { + >::type_info() + } + + fn compatible(ty: &DB::TypeInfo) -> bool { + ty.is_null() || >::compatible(ty) + } +} diff --git a/tests/postgres/types.rs b/tests/postgres/types.rs index ed169ee1da..7aa81617bb 100644 --- a/tests/postgres/types.rs +++ b/tests/postgres/types.rs @@ -3,6 +3,7 @@ extern crate time_ as time; use std::borrow::Cow; use std::net::SocketAddr; use std::ops::Bound; +use std::rc::Rc; use std::sync::Arc; use sqlx::postgres::types::{Oid, PgCiText, PgInterval, PgMoney, PgRange}; @@ -664,7 +665,7 @@ CREATE TEMPORARY TABLE user_login ( async fn test_arc() -> anyhow::Result<()> { let mut conn = new::().await?; - let user_age: Arc = sqlx::query_scalar("select $1 as age ") + let user_age: Arc = sqlx::query_scalar("SELECT $1 AS age ") .bind(Arc::new(1i32)) .fetch_one(&mut conn) .await?; @@ -678,7 +679,7 @@ async fn test_cow() -> anyhow::Result<()> { let age: Cow<'_, i32> = Cow::Owned(1i32); - let user_age: Cow<'static, i32> = sqlx::query_scalar("select $1 as age ") + let user_age: Cow<'static, i32> = sqlx::query_scalar("SELECT $1 AS age ") .bind(age) .fetch_one(&mut conn) .await?; @@ -691,7 +692,7 @@ async fn test_cow() -> anyhow::Result<()> { async fn test_box() -> anyhow::Result<()> { let mut conn = new::().await?; - let user_age: Box = sqlx::query_scalar("select $1 as age ") + let user_age: Box = sqlx::query_scalar("SELECT $1 AS age ") .bind(Box::new(1)) .fetch_one(&mut conn) .await?; @@ -699,3 +700,16 @@ async fn test_box() -> anyhow::Result<()> { assert!(user_age.as_ref() == &1); Ok(()) } + +#[sqlx_macros::test] +async fn test_rc() -> anyhow::Result<()> { + let mut conn = new::().await?; + + let user_age: i32 = sqlx::query_scalar("SELECT $1 AS age") + .bind(Rc::new(1i32)) + .fetch_one(&mut conn) + .await?; + + assert!(user_age == 1); + Ok(()) +}