sqlx/tests/postgres-macros.rs
Oliver Bøving 0de4b5186b Add the array types to the query! macro
This still needs some work, as the inferance and error messages are not
quite where we want them to be
2020-02-25 21:56:07 +01:00

211 lines
5.2 KiB
Rust

use sqlx::{Connect, Executor, PgConnection};
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
async fn test_query() -> anyhow::Result<()> {
let mut conn = connect().await?;
let account = sqlx::query!(
"SELECT * from (VALUES (1, 'Herp Derpinson')) accounts(id, name) where id = $1",
1i32
)
.fetch_one(&mut conn)
.await?;
println!("account ID: {:?}", account.id);
Ok(())
}
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
async fn test_no_result() -> anyhow::Result<()> {
let mut conn = connect().await?;
let _ = sqlx::query!("DELETE FROM pg_enum")
.execute(&mut conn)
.await?;
Ok(())
}
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
async fn _file() -> anyhow::Result<()> {
let mut conn = connect().await?;
let account = sqlx::query_file!("tests/test-query.sql")
.fetch_one(&mut conn)
.await?;
println!("{:?}", account);
Ok(())
}
#[derive(Debug)]
struct Account {
id: i32,
name: Option<String>,
}
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
async fn test_query_as() -> anyhow::Result<()> {
let mut conn = connect().await?;
let account = sqlx::query_as!(
Account,
"SELECT * from (VALUES (1, null)) accounts(id, name)"
)
.fetch_one(&mut conn)
.await?;
assert_eq!(None, account.name);
println!("{:?}", account);
Ok(())
}
#[derive(Debug)]
struct RawAccount {
r#type: i32,
name: Option<String>,
}
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
async fn test_query_as_raw() -> anyhow::Result<()> {
let mut conn = connect().await?;
let account = sqlx::query_as!(
RawAccount,
"SELECT * from (VALUES (1, null)) accounts(type, name)"
)
.fetch_one(&mut conn)
.await?;
assert_eq!(None, account.name);
assert_eq!(1, account.r#type);
println!("{:?}", account);
Ok(())
}
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
async fn test_query_file_as() -> anyhow::Result<()> {
let mut conn = connect().await?;
let account = sqlx::query_file_as!(Account, "tests/test-query.sql")
.fetch_one(&mut conn)
.await?;
println!("{:?}", account);
Ok(())
}
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
async fn query_by_string() -> anyhow::Result<()> {
let mut conn = connect().await?;
let string = "Hello, world!".to_string();
let result = sqlx::query!(
"SELECT * from (VALUES('Hello, world!')) strings(string)\
where string = $1 or string = $2",
string,
string[..]
)
.fetch_one(&mut conn)
.await?;
assert_eq!(result.string, string);
Ok(())
}
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
async fn test_nullable_err() -> anyhow::Result<()> {
#[derive(Debug)]
struct Account {
id: i32,
name: String,
}
let mut conn = connect().await?;
let err = sqlx::query_as!(
Account,
"SELECT * from (VALUES (1, null::text)) accounts(id, name)"
)
.fetch_one(&mut conn)
.await
.unwrap_err();
if let sqlx::Error::Decode(sqlx::decode::DecodeError::UnexpectedNull) = err {
Ok(())
} else {
panic!("expected `UnexpectedNull`, got {}", err)
}
}
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
async fn test_many_args() -> anyhow::Result<()> {
let mut conn = connect().await?;
// previous implementation would only have supported 10 bind parameters
// (this is really gross to test in MySQL)
let rows = sqlx::query!(
"SELECT * from unnest(array[$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12]::int[]) ids(id);",
0i32, 1i32, 2i32, 3i32, 4i32, 5i32, 6i32, 7i32, 8i32, 9i32, 10i32, 11i32
)
.fetch_all(&mut conn)
.await?;
for (i, row) in rows.iter().enumerate() {
assert_eq!(i as i32, row.id);
}
Ok(())
}
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
async fn test_array_from_slice() -> anyhow::Result<()> {
let mut conn = connect().await?;
let list: &[i32] = &[1, 2, 3, 4i32];
let result = sqlx::query!("SELECT $1::int[] as my_array", *list)
.fetch_one(&mut conn)
.await?;
assert_eq!(result.my_array, vec![1, 2, 3, 4]);
println!("result ID: {:?}", result.my_array);
let account = sqlx::query!("SELECT ARRAY[4,3,2,1] as my_array")
.fetch_one(&mut conn)
.await?;
assert_eq!(account.my_array, vec![4, 3, 2, 1]);
println!("account ID: {:?}", account.my_array);
Ok(())
}
async fn connect() -> anyhow::Result<PgConnection> {
let _ = dotenv::dotenv();
let _ = env_logger::try_init();
Ok(PgConnection::connect(dotenv::var("DATABASE_URL")?).await?)
}