mirror of
https://github.com/launchbadge/sqlx
synced 2024-09-20 14:21:57 +00:00
postgres: fix various issues and add more tests
This commit is contained in:
parent
433aab1e5b
commit
8e8cf6db20
8 changed files with 123 additions and 78 deletions
|
@ -76,7 +76,7 @@ name = "postgres"
|
|||
required-features = [ "postgres" ]
|
||||
|
||||
[[test]]
|
||||
name = "postgres-unprepared"
|
||||
name = "postgres-simple"
|
||||
required-features = [ "postgres" ]
|
||||
|
||||
[[test]]
|
||||
|
|
|
@ -7,6 +7,7 @@ use crate::decode::Decode;
|
|||
use crate::encode::Encode;
|
||||
use crate::postgres::protocol::TypeId;
|
||||
use crate::postgres::types::PgTypeInfo;
|
||||
use crate::postgres::row::PgValue;
|
||||
use crate::postgres::Postgres;
|
||||
use crate::types::Type;
|
||||
|
||||
|
@ -65,8 +66,8 @@ where
|
|||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for NaiveTime {
|
||||
fn decode(raw: &'de [u8]) -> crate::Result<Self> {
|
||||
let micros: i64 = Decode::<Postgres>::decode(raw)?;
|
||||
fn decode(value: Option<PgValue<'de>>) -> crate::Result<Self> {
|
||||
let micros: i64 = Decode::<Postgres>::decode(value)?;
|
||||
|
||||
Ok(NaiveTime::from_hms(0, 0, 0) + Duration::microseconds(micros))
|
||||
}
|
||||
|
@ -87,8 +88,8 @@ impl Encode<Postgres> for NaiveTime {
|
|||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for NaiveDate {
|
||||
fn decode(raw: &'de [u8]) -> crate::Result<Self> {
|
||||
let days: i32 = Decode::<Postgres>::decode(raw)?;
|
||||
fn decode(value: Option<PgValue<'de>>) -> crate::Result<Self> {
|
||||
let days: i32 = Decode::<Postgres>::decode(value)?;
|
||||
|
||||
Ok(NaiveDate::from_ymd(2000, 1, 1) + Duration::days(days as i64))
|
||||
}
|
||||
|
@ -112,8 +113,8 @@ impl Encode<Postgres> for NaiveDate {
|
|||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for NaiveDateTime {
|
||||
fn decode(raw: &'de [u8]) -> crate::Result<Self> {
|
||||
let micros: i64 = Decode::<Postgres>::decode(raw)?;
|
||||
fn decode(value: Option<PgValue<'de>>) -> crate::Result<Self> {
|
||||
let micros: i64 = Decode::<Postgres>::decode(value)?;
|
||||
|
||||
postgres_epoch()
|
||||
.naive_utc()
|
||||
|
@ -146,15 +147,15 @@ impl Encode<Postgres> for NaiveDateTime {
|
|||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for DateTime<Utc> {
|
||||
fn decode(raw: &'de [u8]) -> crate::Result<Self> {
|
||||
let date_time = Decode::<Postgres>::decode(raw)?;
|
||||
fn decode(value: Option<PgValue<'de>>) -> crate::Result<Self> {
|
||||
let date_time = Decode::<Postgres>::decode(value)?;
|
||||
Ok(DateTime::from_utc(date_time, Utc))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for DateTime<Local> {
|
||||
fn decode(raw: &'de [u8]) -> crate::Result<Self> {
|
||||
let date_time = Decode::<Postgres>::decode(raw)?;
|
||||
fn decode(value: Option<PgValue<'de>>) -> crate::Result<Self> {
|
||||
let date_time = Decode::<Postgres>::decode(value)?;
|
||||
Ok(Local.from_utc_datetime(&date_time))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,6 +49,6 @@ impl Encode<Postgres> for f64 {
|
|||
|
||||
impl<'de> Decode<'de, Postgres> for f64 {
|
||||
fn decode(value: Option<PgValue<'de>>) -> crate::Result<Self> {
|
||||
<i32 as Decode<Postgres>>::decode(value).map(|value| f64::from_bits(value as u64))
|
||||
<i64 as Decode<Postgres>>::decode(value).map(|value| f64::from_bits(value as u64))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
use std::convert::TryInto;
|
||||
use std::str::FromStr;
|
||||
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::decode::Decode;
|
||||
use crate::encode::Encode;
|
||||
use crate::postgres::row::PgValue;
|
||||
use crate::postgres::protocol::TypeId;
|
||||
use crate::postgres::types::PgTypeInfo;
|
||||
use crate::postgres::Postgres;
|
||||
|
@ -26,7 +30,10 @@ impl Encode<Postgres> for Uuid {
|
|||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for Uuid {
|
||||
fn decode(buf: &'de [u8]) -> crate::Result<Self> {
|
||||
Uuid::from_slice(buf).map_err(|err| crate::Error::Decode(Box::new(err)))
|
||||
fn decode(value: Option<PgValue<'de>>) -> crate::Result<Self> {
|
||||
match value.try_into()? {
|
||||
PgValue::Binary(buf) => Uuid::from_slice(buf).map_err(|err| crate::Error::decode(err)),
|
||||
PgValue::Text(s) => Uuid::from_str(s).map_err(|err| crate::Error::decode(err)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use sqlx::{Connect, Executor, Cursor, Row, PgConnection};
|
||||
use sqlx::postgres::PgRow;
|
||||
|
||||
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
|
||||
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
|
||||
|
@ -19,7 +20,7 @@ async fn test_select_1() -> anyhow::Result<()> {
|
|||
let mut cursor = conn.fetch("SELECT 5");
|
||||
let row = cursor.next().await?.unwrap();
|
||||
|
||||
assert_eq!(5i32, row.get(0)?);
|
||||
assert!(5i32 == row.get::<i32, _>(0)?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -48,12 +49,48 @@ SELECT id, text FROM _sqlx_test_postgres_5112;
|
|||
|
||||
let row = cursor.next().await?.unwrap();
|
||||
|
||||
assert_eq!(1_i64, row.get(0)?);
|
||||
assert!("this is a test" == row.get::<&str, _>(1)?);
|
||||
let id: i64 = row.get(0)?;
|
||||
let text: &str = row.get(1)?;
|
||||
|
||||
assert!(1_i64 == id);
|
||||
assert!("this is a test" == text);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
macro_rules! test {
|
||||
($name:ident: $ty:ty: $($text:literal == $value:expr),+) => {
|
||||
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
|
||||
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
|
||||
async fn $name () -> anyhow::Result<()> {
|
||||
let mut conn = connect().await?;
|
||||
|
||||
$(
|
||||
let rec: $ty = sqlx::query(&format!("SELECT $1 as _1"))
|
||||
.bind($value)
|
||||
.map(|row: PgRow| row.get(0))
|
||||
.fetch_one(&mut conn)
|
||||
.await?;
|
||||
|
||||
assert!($value == rec);
|
||||
)+
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test!(postgres_simple_bool: bool: "false::boolean" == false, "true::boolean" == true);
|
||||
|
||||
test!(postgres_simple_smallint: i16: "821::smallint" == 821_i16);
|
||||
test!(postgres_simple_int: i32: "94101::int" == 94101_i32);
|
||||
test!(postgres_simple_bigint: i64: "9358295312::bigint" == 9358295312_i64);
|
||||
|
||||
test!(postgres_simple_real: f32: "9419.122::real" == 9419.122_f32);
|
||||
test!(postgres_simple_double: f64: "939399419.1225182::double precision" == 939399419.1225182_f64);
|
||||
|
||||
test!(postgres_simple_text: String: "'this is foo'" == "this is foo", "''" == "");
|
||||
|
||||
async fn connect() -> anyhow::Result<PgConnection> {
|
||||
let _ = dotenv::dotenv();
|
||||
let _ = env_logger::try_init();
|
|
@ -25,7 +25,7 @@ async fn postgres_chrono_date() -> anyhow::Result<()> {
|
|||
|
||||
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
|
||||
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
|
||||
async fn mysql_chrono_date_time() -> anyhow::Result<()> {
|
||||
async fn postgres_chrono_date_time() -> anyhow::Result<()> {
|
||||
let mut conn = connect().await?;
|
||||
|
||||
let value = NaiveDate::from_ymd(2019, 1, 2).and_hms(5, 10, 20);
|
||||
|
|
|
@ -1,59 +1,59 @@
|
|||
// use sqlx::{postgres::PgConnection, Connect as _, Connection as _, Row};
|
||||
//
|
||||
// async fn connect() -> anyhow::Result<PgConnection> {
|
||||
// Ok(PgConnection::connect(dotenv::var("DATABASE_URL")?).await?)
|
||||
// }
|
||||
//
|
||||
// macro_rules! test {
|
||||
// ($name:ident: $ty:ty: $($text:literal == $value:expr),+) => {
|
||||
// #[cfg_attr(feature = "runtime-async-std", async_std::test)]
|
||||
// #[cfg_attr(feature = "runtime-tokio", tokio::test)]
|
||||
// async fn $name () -> anyhow::Result<()> {
|
||||
// let mut conn = connect().await?;
|
||||
//
|
||||
// $(
|
||||
// let row = sqlx::query(&format!("SELECT {} = $1, $1 as _1", $text))
|
||||
// .bind($value)
|
||||
// .fetch_one(&mut conn)
|
||||
// .await?;
|
||||
//
|
||||
// assert!(row.get::<bool, _>(0));
|
||||
// assert!($value == row.get::<$ty, _>("_1"));
|
||||
// )+
|
||||
//
|
||||
// Ok(())
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// test!(postgres_bool: bool: "false::boolean" == false, "true::boolean" == true);
|
||||
//
|
||||
// test!(postgres_smallint: i16: "821::smallint" == 821_i16);
|
||||
// test!(postgres_int: i32: "94101::int" == 94101_i32);
|
||||
// test!(postgres_bigint: i64: "9358295312::bigint" == 9358295312_i64);
|
||||
//
|
||||
// test!(postgres_real: f32: "9419.122::real" == 9419.122_f32);
|
||||
// test!(postgres_double: f64: "939399419.1225182::double precision" == 939399419.1225182_f64);
|
||||
//
|
||||
// test!(postgres_text: String: "'this is foo'" == "this is foo", "''" == "");
|
||||
//
|
||||
// #[cfg_attr(feature = "runtime-async-std", async_std::test)]
|
||||
// #[cfg_attr(feature = "runtime-tokio", tokio::test)]
|
||||
// async fn postgres_bytes() -> anyhow::Result<()> {
|
||||
// let mut conn = connect().await?;
|
||||
//
|
||||
// let value = b"Hello, World";
|
||||
//
|
||||
// let row = sqlx::query("SELECT E'\\\\x48656c6c6f2c20576f726c64' = $1, $1")
|
||||
// .bind(&value[..])
|
||||
// .fetch_one(&mut conn)
|
||||
// .await?;
|
||||
//
|
||||
// assert!(row.get::<bool, _>(0));
|
||||
//
|
||||
// let output: Vec<u8> = row.get(1);
|
||||
//
|
||||
// assert_eq!(&value[..], &*output);
|
||||
//
|
||||
// Ok(())
|
||||
// }
|
||||
use sqlx::{PgConnection, Connect, Row};
|
||||
use sqlx::postgres::PgRow;
|
||||
|
||||
async fn connect() -> anyhow::Result<PgConnection> {
|
||||
Ok(PgConnection::connect(dotenv::var("DATABASE_URL")?).await?)
|
||||
}
|
||||
|
||||
macro_rules! test {
|
||||
($name:ident: $ty:ty: $($text:literal == $value:expr),+) => {
|
||||
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
|
||||
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
|
||||
async fn $name () -> anyhow::Result<()> {
|
||||
let mut conn = connect().await?;
|
||||
|
||||
$(
|
||||
let rec: (bool, $ty) = sqlx::query(&format!("SELECT {} = $1, $1 as _1", $text))
|
||||
.bind($value)
|
||||
.map(|row: PgRow| Ok((row.get(0)?, row.get(1)?)))
|
||||
.fetch_one(&mut conn)
|
||||
.await?;
|
||||
|
||||
assert!(rec.0);
|
||||
assert!($value == rec.1);
|
||||
)+
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test!(postgres_bool: bool: "false::boolean" == false, "true::boolean" == true);
|
||||
|
||||
test!(postgres_smallint: i16: "821::smallint" == 821_i16);
|
||||
test!(postgres_int: i32: "94101::int" == 94101_i32);
|
||||
test!(postgres_bigint: i64: "9358295312::bigint" == 9358295312_i64);
|
||||
|
||||
test!(postgres_real: f32: "9419.122::real" == 9419.122_f32);
|
||||
test!(postgres_double: f64: "939399419.1225182::double precision" == 939399419.1225182_f64);
|
||||
|
||||
test!(postgres_text: String: "'this is foo'" == "this is foo", "''" == "");
|
||||
|
||||
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
|
||||
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
|
||||
async fn postgres_bytes() -> anyhow::Result<()> {
|
||||
let mut conn = connect().await?;
|
||||
|
||||
let value = b"Hello, World";
|
||||
|
||||
let rec: (bool, Vec<u8>) = sqlx::query("SELECT E'\\\\x48656c6c6f2c20576f726c64' = $1, $1")
|
||||
.bind(&value[..])
|
||||
.map(|row: PgRow| Ok((row.get(0)?, row.get(1)?)))
|
||||
.fetch_one(&mut conn)
|
||||
.await?;
|
||||
|
||||
assert!(rec.0);
|
||||
assert_eq!(&value[..], &*rec.1);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@ use futures::TryStreamExt;
|
|||
use sqlx::{
|
||||
postgres::PgConnection, Connect, Executor, Row,
|
||||
};
|
||||
use sqlx_core::postgres::{PgPool, PgRow};
|
||||
use std::time::Duration;
|
||||
use sqlx::postgres::{PgPool, PgRow};
|
||||
|
||||
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
|
||||
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
|
||||
|
|
Loading…
Reference in a new issue