Move to sqlx::query( ... ).execute style API

This commit is contained in:
Ryan Leckey
2019-08-15 23:03:25 -07:00
parent b8857af916
commit c280ad587f
26 changed files with 776 additions and 671 deletions

View File

@@ -7,8 +7,7 @@ edition = "2018"
sqlx = { path = "../..", features = [ "postgres" ] }
failure = "0.1.5"
env_logger = "0.6.2"
runtime = { version = "=0.3.0-alpha.6", default-features = false }
runtime-tokio = { version = "=0.3.0-alpha.5" }
tokio = { version = "=0.2.0-alpha.1" }
futures-preview = "=0.3.0-alpha.17"
fake = { version = "2.0", features=[ "derive" ] }
rand = "0.7.0"

View File

@@ -1,4 +1,4 @@
#![feature(async_await)]
#![feature(async_await, try_blocks)]
use failure::Fallible;
use fake::{
@@ -9,10 +9,17 @@ use fake::{
},
Dummy, Fake, Faker,
};
use futures::future;
use sqlx::{pg::Pg, Client, Connection, Query};
use std::time::Duration;
use futures::stream::TryStreamExt;
use std::io;
use sqlx::{
pg::{Pg, PgQuery},
Pool, Query, Connection,
};
use std::time::Instant;
type PgPool = Pool<Pg>;
#[derive(Debug, Dummy)]
struct Contact {
#[dummy(faker = "Name()")]
@@ -31,16 +38,22 @@ struct Contact {
phone: String,
}
#[runtime::main(runtime_tokio::Tokio)]
#[tokio::main]
async fn main() -> Fallible<()> {
env_logger::try_init()?;
let client = Client::<Pg>::new("postgres://postgres@localhost/sqlx__dev");
let pool = PgPool::new("postgres://postgres@127.0.0.1/sqlx__dev", 1);
{
let mut conn = client.get().await?;
conn.prepare(
r#"
ensure_schema(&pool).await?;
insert(&pool, 500).await?;
select(&pool, 50_000).await?;
Ok(())
}
async fn ensure_schema(pool: &PgPool) -> io::Result<()> {
sqlx::query::<PgQuery>(
r#"
CREATE TABLE IF NOT EXISTS contacts (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
@@ -50,27 +63,29 @@ CREATE TABLE IF NOT EXISTS contacts (
email TEXT NOT NULL,
phone TEXT NOT NULL
)
"#,
)
.execute()
"#,
)
.execute(&pool)
.await?;
sqlx::query::<PgQuery>("TRUNCATE contacts")
.execute(&pool)
.await?;
conn.prepare("TRUNCATE contacts").execute().await?;
}
Ok(())
}
let mut handles = vec![];
async fn insert(pool: &PgPool, count: usize) -> io::Result<()> {
let start_at = Instant::now();
let rows = 10_000;
for _ in 0..rows {
let client = client.clone();
for _ in 0..count {
let pool = pool.clone();
let contact: Contact = Faker.fake();
let handle: runtime::task::JoinHandle<Fallible<()>> = runtime::task::spawn(async move {
let mut conn = client.get().await?;
conn.prepare(
sqlx::query::<PgQuery>(
r#"
INSERT INTO contacts (name, username, password, email, phone)
VALUES ($1, $2, $3, $4, $5)
INSERT INTO contacts (name, username, password, email, phone)
VALUES ($1, $2, $3, $4, $5)
"#,
)
.bind(contact.name)
@@ -78,18 +93,38 @@ CREATE TABLE IF NOT EXISTS contacts (
.bind(contact.password)
.bind(contact.email)
.bind(contact.phone)
.execute()
.execute(&pool)
.await?;
Ok(())
});
handles.push(handle);
}
future::join_all(handles).await;
let elapsed = start_at.elapsed();
let per = Duration::from_nanos((elapsed.as_nanos() / (count as u128)) as u64);
println!("insert {} rows in {:?}", rows, start_at.elapsed());
println!("insert {} rows in {:?} [ 1 in ~{:?} ]", count, elapsed, per);
Ok(())
}
async fn select(pool: &PgPool, iterations: usize) -> io::Result<()> {
let start_at = Instant::now();
let mut rows: usize = 0;
for _ in 0..iterations {
// TODO: Once we have FromRow derives we can replace this with Vec<Contact>
let contacts: Vec<(String, String, String, String, String)> = sqlx::query::<PgQuery>(
r#"
SELECT name, username, password, email, phone
FROM contacts
"#,
).fetch(&pool).try_collect().await?;
rows = contacts.len();
}
let elapsed = start_at.elapsed();
let per = Duration::from_nanos((elapsed.as_nanos() / (iterations as u128)) as u64);
println!("select {} rows in ~{:?} [ x{} in {:?} ]", rows, per, iterations, elapsed);
Ok(())
}

View File

@@ -7,7 +7,6 @@ edition = "2018"
sqlx = { path = "../..", features = [ "postgres" ] }
failure = "0.1.5"
env_logger = "0.6.2"
runtime = { version = "=0.3.0-alpha.6", default-features = false }
runtime-tokio = { version = "=0.3.0-alpha.5" }
tokio = { version = "=0.2.0-alpha.1" }
futures-preview = "=0.3.0-alpha.17"
structopt = "0.2.18"

View File

@@ -2,7 +2,10 @@
use failure::Fallible;
use futures::{future, TryStreamExt};
use sqlx::{pg::PgConnection, Connection, Query};
use sqlx::{
pg::{Pg, PgQuery},
Connection, Query,
};
use structopt::StructOpt;
#[derive(StructOpt, Debug)]
@@ -20,13 +23,13 @@ enum Command {
MarkAsDone { id: i64 },
}
#[runtime::main(runtime_tokio::Tokio)]
#[tokio::main]
async fn main() -> Fallible<()> {
env_logger::try_init()?;
let opt = Options::from_args();
let mut conn = PgConnection::establish("postgres://postgres@localhost/sqlx__dev").await?;
let mut conn = Connection::<Pg>::establish("postgres://postgres@127.0.0.1/sqlx__dev").await?;
ensure_schema(&mut conn).await?;
@@ -47,11 +50,11 @@ async fn main() -> Fallible<()> {
Ok(())
}
async fn ensure_schema(conn: &mut PgConnection) -> Fallible<()> {
conn.prepare("BEGIN").execute().await?;
async fn ensure_schema(conn: &mut Connection<Pg>) -> Fallible<()> {
sqlx::query::<PgQuery>("BEGIN").execute(conn).await?;
// language=sql
conn.prepare(
sqlx::query::<PgQuery>(
r#"
CREATE TABLE IF NOT EXISTS tasks (
id BIGSERIAL PRIMARY KEY,
@@ -61,24 +64,24 @@ CREATE TABLE IF NOT EXISTS tasks (
)
"#,
)
.execute()
.execute(conn)
.await?;
conn.prepare("COMMIT").execute().await?;
sqlx::query::<PgQuery>("COMMIT").execute(conn).await?;
Ok(())
}
async fn print_all_tasks(conn: &mut PgConnection) -> Fallible<()> {
async fn print_all_tasks(conn: &mut Connection<Pg>) -> Fallible<()> {
// language=sql
conn.prepare(
sqlx::query::<PgQuery>(
r#"
SELECT id, text
FROM tasks
WHERE done_at IS NULL
"#,
)
.fetch()
.fetch(conn)
.try_for_each(|(id, text): (i64, String)| {
// language=text
println!("{:>5} | {}", id, text);
@@ -90,24 +93,24 @@ WHERE done_at IS NULL
Ok(())
}
async fn add_task(conn: &mut PgConnection, text: &str) -> Fallible<()> {
async fn add_task(conn: &mut Connection<Pg>, text: &str) -> Fallible<()> {
// language=sql
conn.prepare(
sqlx::query::<PgQuery>(
r#"
INSERT INTO tasks ( text )
VALUES ( $1 )
"#,
)
.bind(text)
.execute()
.execute(conn)
.await?;
Ok(())
}
async fn mark_task_as_done(conn: &mut PgConnection, id: i64) -> Fallible<()> {
async fn mark_task_as_done(conn: &mut Connection<Pg>, id: i64) -> Fallible<()> {
// language=sql
conn.prepare(
sqlx::query::<PgQuery>(
r#"
UPDATE tasks
SET done_at = now()
@@ -115,7 +118,7 @@ WHERE id = $1
"#,
)
.bind(id)
.execute()
.execute(conn)
.await?;
Ok(())