2019-11-23 02:37:27 +00:00
|
|
|
use crate::{BinaryCopyInStream, BinaryCopyOutStream};
|
2019-11-18 02:28:12 +00:00
|
|
|
use tokio_postgres::types::Type;
|
|
|
|
use tokio_postgres::{Client, NoTls};
|
2019-11-23 02:37:27 +00:00
|
|
|
use futures::TryStreamExt;
|
2019-11-18 02:28:12 +00:00
|
|
|
|
|
|
|
async fn connect() -> Client {
|
|
|
|
let (client, connection) =
|
|
|
|
tokio_postgres::connect("host=localhost port=5433 user=postgres", NoTls)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
tokio::spawn(async {
|
|
|
|
connection.await.unwrap();
|
|
|
|
});
|
|
|
|
client
|
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
async fn write_basic() {
|
|
|
|
let client = connect().await;
|
|
|
|
|
|
|
|
client
|
|
|
|
.batch_execute("CREATE TEMPORARY TABLE foo (id INT, bar TEXT)")
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
2019-11-23 02:37:27 +00:00
|
|
|
let stream = BinaryCopyInStream::new(&[Type::INT4, Type::TEXT], |mut w| {
|
2019-11-18 02:28:12 +00:00
|
|
|
async move {
|
2019-11-19 02:06:03 +00:00
|
|
|
w.write(&[&1i32, &"foobar"]).await?;
|
|
|
|
w.write(&[&2i32, &None::<&str>]).await?;
|
2019-11-18 02:28:12 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
client
|
|
|
|
.copy_in("COPY foo (id, bar) FROM STDIN BINARY", &[], stream)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
2019-11-19 02:06:03 +00:00
|
|
|
let rows = client
|
|
|
|
.query("SELECT id, bar FROM foo ORDER BY id", &[])
|
|
|
|
.await
|
|
|
|
.unwrap();
|
2019-11-18 02:28:12 +00:00
|
|
|
assert_eq!(rows.len(), 2);
|
|
|
|
assert_eq!(rows[0].get::<_, i32>(0), 1);
|
|
|
|
assert_eq!(rows[0].get::<_, Option<&str>>(1), Some("foobar"));
|
|
|
|
assert_eq!(rows[1].get::<_, i32>(0), 2);
|
|
|
|
assert_eq!(rows[1].get::<_, Option<&str>>(1), None);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
async fn write_many_rows() {
|
|
|
|
let client = connect().await;
|
|
|
|
|
|
|
|
client
|
|
|
|
.batch_execute("CREATE TEMPORARY TABLE foo (id INT, bar TEXT)")
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
2019-11-23 02:37:27 +00:00
|
|
|
let stream = BinaryCopyInStream::new(&[Type::INT4, Type::TEXT], |mut w| {
|
2019-11-19 02:06:03 +00:00
|
|
|
async move {
|
|
|
|
for i in 0..10_000i32 {
|
|
|
|
w.write(&[&i, &format!("the value for {}", i)]).await?;
|
|
|
|
}
|
2019-11-18 02:28:12 +00:00
|
|
|
|
2019-11-19 02:06:03 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
2019-11-18 02:28:12 +00:00
|
|
|
});
|
|
|
|
|
2019-11-19 02:06:03 +00:00
|
|
|
client
|
|
|
|
.copy_in("COPY foo (id, bar) FROM STDIN BINARY", &[], stream)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
2019-11-18 02:28:12 +00:00
|
|
|
|
2019-11-19 02:06:03 +00:00
|
|
|
let rows = client
|
|
|
|
.query("SELECT id, bar FROM foo ORDER BY id", &[])
|
|
|
|
.await
|
|
|
|
.unwrap();
|
2019-11-18 02:28:12 +00:00
|
|
|
for (i, row) in rows.iter().enumerate() {
|
|
|
|
assert_eq!(row.get::<_, i32>(0), i as i32);
|
|
|
|
assert_eq!(row.get::<_, &str>(1), format!("the value for {}", i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
async fn write_big_rows() {
|
|
|
|
let client = connect().await;
|
|
|
|
|
2019-11-19 02:06:03 +00:00
|
|
|
client
|
|
|
|
.batch_execute("CREATE TEMPORARY TABLE foo (id INT, bar BYTEA)")
|
|
|
|
.await
|
|
|
|
.unwrap();
|
2019-11-18 02:28:12 +00:00
|
|
|
|
2019-11-23 02:37:27 +00:00
|
|
|
let stream = BinaryCopyInStream::new(&[Type::INT4, Type::BYTEA], |mut w| {
|
2019-11-18 02:28:12 +00:00
|
|
|
async move {
|
|
|
|
for i in 0..2i32 {
|
2019-11-19 02:06:03 +00:00
|
|
|
w.write(&[&i, &vec![i as u8; 128 * 1024]]).await?;
|
2019-11-18 02:28:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2019-11-19 02:06:03 +00:00
|
|
|
client
|
|
|
|
.copy_in("COPY foo (id, bar) FROM STDIN BINARY", &[], stream)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
2019-11-18 02:28:12 +00:00
|
|
|
|
2019-11-19 02:06:03 +00:00
|
|
|
let rows = client
|
|
|
|
.query("SELECT id, bar FROM foo ORDER BY id", &[])
|
|
|
|
.await
|
|
|
|
.unwrap();
|
2019-11-18 02:28:12 +00:00
|
|
|
for (i, row) in rows.iter().enumerate() {
|
|
|
|
assert_eq!(row.get::<_, i32>(0), i as i32);
|
|
|
|
assert_eq!(row.get::<_, &[u8]>(1), &*vec![i as u8; 128 * 1024]);
|
|
|
|
}
|
|
|
|
}
|
2019-11-23 02:37:27 +00:00
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
async fn read_basic() {
|
|
|
|
let client = connect().await;
|
|
|
|
|
|
|
|
client
|
|
|
|
.batch_execute(
|
|
|
|
"
|
|
|
|
CREATE TEMPORARY TABLE foo (id INT, bar TEXT);
|
|
|
|
INSERT INTO foo (id, bar) VALUES (1, 'foobar'), (2, NULL);
|
|
|
|
"
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let stream = client.copy_out("COPY foo (id, bar) TO STDIN BINARY", &[]).await.unwrap();
|
|
|
|
let rows = BinaryCopyOutStream::new(&[Type::INT4, Type::TEXT], stream).try_collect::<Vec<_>>().await.unwrap();
|
|
|
|
assert_eq!(rows.len(), 2);
|
|
|
|
|
|
|
|
assert_eq!(rows[0].get::<i32>(0), 1);
|
|
|
|
assert_eq!(rows[0].get::<Option<&str>>(1), Some("foobar"));
|
|
|
|
assert_eq!(rows[1].get::<i32>(0), 2);
|
|
|
|
assert_eq!(rows[1].get::<Option<&str>>(1), None);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
async fn read_many_rows() {
|
|
|
|
let client = connect().await;
|
|
|
|
|
|
|
|
client
|
|
|
|
.batch_execute(
|
|
|
|
"
|
|
|
|
CREATE TEMPORARY TABLE foo (id INT, bar TEXT);
|
|
|
|
INSERT INTO foo (id, bar) SELECT i, 'the value for ' || i FROM generate_series(0, 9999) i;"
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let stream = client.copy_out("COPY foo (id, bar) TO STDIN BINARY", &[]).await.unwrap();
|
|
|
|
let rows = BinaryCopyOutStream::new(&[Type::INT4, Type::TEXT], stream).try_collect::<Vec<_>>().await.unwrap();
|
|
|
|
assert_eq!(rows.len(), 10_000);
|
|
|
|
|
|
|
|
for (i, row) in rows.iter().enumerate() {
|
|
|
|
assert_eq!(row.get::<i32>(0), i as i32);
|
|
|
|
assert_eq!(row.get::<&str>(1), format!("the value for {}", i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
async fn read_big_rows() {
|
|
|
|
let client = connect().await;
|
|
|
|
|
|
|
|
client
|
|
|
|
.batch_execute("CREATE TEMPORARY TABLE foo (id INT, bar BYTEA)")
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
for i in 0..2i32 {
|
|
|
|
client.execute("INSERT INTO foo (id, bar) VALUES ($1, $2)", &[&i, &vec![i as u8; 128 * 1024]]).await.unwrap();
|
|
|
|
}
|
|
|
|
|
|
|
|
let stream = client.copy_out("COPY foo (id, bar) TO STDIN BINARY", &[]).await.unwrap();
|
|
|
|
let rows = BinaryCopyOutStream::new(&[Type::INT4, Type::BYTEA], stream).try_collect::<Vec<_>>().await.unwrap();
|
|
|
|
assert_eq!(rows.len(), 2);
|
|
|
|
|
|
|
|
for (i, row) in rows.iter().enumerate() {
|
|
|
|
assert_eq!(row.get::<i32>(0), i as i32);
|
|
|
|
assert_eq!(row.get::<&[u8]>(1), &vec![i as u8; 128 * 1024][..]);
|
|
|
|
}
|
|
|
|
}
|