use std::sync::Arc;
use anyhow::Result;
use sqll::{OpenOptions, PoolBuilder, SendStatement, Statements};
use tokio::task;
#[derive(Statements)]
#[sql(read_only)]
struct Read {
#[sql = "SELECT name, age FROM users ORDER BY age"]
all_users: SendStatement,
}
#[derive(Statements)]
struct Write {
#[sql = "INSERT INTO users (name, age) VALUES (?, ?)"]
insert_user: SendStatement,
}
#[tokio::main]
async fn main() -> Result<()> {
let dir = tempfile::TempDir::new()?;
let path = dir.path().join("pool.db");
{
let c = OpenOptions::new()
.create()
.read_write()
.no_mutex()
.open(&path)?;
c.execute("CREATE TABLE users (name TEXT PRIMARY KEY NOT NULL, age INTEGER)")?;
}
let mut options = OpenOptions::new();
options.no_mutex().create();
let pool = Arc::new(PoolBuilder::new(options, 4).open::<Read, Write>(&path)?);
{
let guard = pool.clone().exclusive().await?;
task::spawn_blocking(move || -> Result<()> {
let mut guard = guard;
for (name, age) in [("Alice", 42), ("Bob", 52), ("Charlie", 20)] {
guard.insert_user.execute((name, age))?;
guard.insert_user.reset()?;
}
Ok(())
})
.await??;
}
let mut tasks = Vec::new();
for _ in 0..4 {
let pool = pool.clone();
tasks.push(task::spawn(async move {
let guard = pool.shared().await?;
task::spawn_blocking(move || -> Result<Vec<(String, i64)>> {
let mut guard = guard;
let mut rows = Vec::new();
while let Some(row) = guard.all_users.next::<(String, i64)>()? {
rows.push(row);
}
guard.all_users.reset()?;
Ok(rows)
})
.await?
}));
}
for t in tasks {
let rows = t.await??;
println!("{rows:?}");
}
Ok(())
}