Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Database Client

Provides a set of functions that establish connections, execute queries and manage data transactions.

Benchmark

Independent benchmarks are available at https://github.com/diesel-rs/metrics.

PostgreSQL

Implements a subset of https://www.postgresql.org/docs/16/protocol.html. PostgreSQL is a robust, open-source relational database management system that, among other things, supports several data types and usually also excels in concurrent scenarios.

To use this functionality, it is necessary to activate the postgres feature.

Example

//! Demonstrates different interactions with a PostgreSQL database.

extern crate tokio;
extern crate wtx;
extern crate wtx_examples;

use wtx::{
  database::{Executor as _, Record, Records},
  misc::into_rslt,
};

#[tokio::main]
async fn main() -> wtx::Result<()> {
  let uri = "postgres://USER:PASSWORD@localhost/DATABASE";
  let mut executor = wtx_examples::executor_postgres(uri).await?;
  executor
    .transaction(|this| async {
      this.execute_ignored("CREATE TABLE IF NOT EXISTS example(id INT, name VARCHAR)").await?;
      this
        .execute_stmt_none("INSERT INTO foo VALUES ($1, $2), ($3, $4)", (1u32, "one", 2u32, "two"))
        .await?;
      Ok(((), this))
    })
    .await?;
  let records = executor
    .execute_stmt_many("SELECT id, name FROM example", (), |_| Ok::<_, wtx::Error>(()))
    .await?;
  let record0 = into_rslt(records.get(0))?;
  let record1 = into_rslt(records.get(1))?;
  assert_eq!((record0.decode::<_, u32>(0)?, record0.decode::<_, &str>("name")?), (1, "one"));
  assert_eq!((record1.decode::<_, u32>("id")?, record1.decode::<_, &str>(1)?), (2, "two"));
  Ok(())
}

Batch

PostgreSQL supports the sending of multiple statements in a single round-trip.

//! Sends multiple commands at once and awaits them.

extern crate tokio;
extern crate wtx;
extern crate wtx_examples;

use wtx::{
  collection::ArrayVectorU8,
  database::{Record, Records},
  misc::into_rslt,
};

const COMMANDS: &[&str] = &["SELECT 0 = $1", "SELECT 1 = $1", "SELECT 2 = $1"];

#[tokio::main]
async fn main() -> wtx::Result<()> {
  let uri = "postgres://USER:PASSWORD@localhost/DATABASE";
  let mut executor = wtx_examples::executor_postgres(uri).await?;
  let mut batch = executor.batch();
  let mut idx: u32 = 0;
  let mut records = ArrayVectorU8::<_, { COMMANDS.len() }>::new();
  for cmd in COMMANDS {
    batch.stmt(cmd, (idx,))?;
    idx = idx.wrapping_add(1);
  }
  batch.flush(&mut records, |_| Ok(())).await?;
  for record in records {
    assert!(into_rslt(record.get(0))?.decode::<_, bool>(0)?);
  }
  Ok(())
}

Tests

The #[wtx::db] macro automatically migrates and seeds individual tests in isolation to allow concurrent evaluations.

Its current state is limited to PostgreSQL tests that use the standard std::net::TcpStream alongside the built-in executor. Connected users must have the right to create new databases.

To use this functionality, it is necessary to activate the database-tests feature.

//! The DB isolation provided by `#[wtx::db]` allows the concurrent execution of identical queries
//! without causing conflicts.
//!
//! The `dir` parameter is optional.

fn main() {}

#[cfg(test)]
mod tests {
  use std::net::TcpStream;
  use wtx::database::{
    Executor, Record,
    client::postgres::{ExecutorBuffer, PostgresExecutor},
  };

  #[wtx::db(dir("../.test-utils"))]
  async fn first_test(conn: PostgresExecutor<wtx::Error, ExecutorBuffer, TcpStream>) {
    common(conn).await;
  }

  #[wtx::db(dir("../.test-utils"))]
  async fn second_test(conn: PostgresExecutor<wtx::Error, ExecutorBuffer, TcpStream>) {
    common(conn).await;
  }

  #[wtx::db(dir("../.test-utils"))]
  async fn third_test(conn: PostgresExecutor<wtx::Error, ExecutorBuffer, TcpStream>) {
    common(conn).await;
  }

  async fn common(mut conn: PostgresExecutor<wtx::Error, ExecutorBuffer, TcpStream>) {
    conn
      .execute_ignored(
        "
          CREATE TABLE foo(id INT PRIMARY KEY, description TEXT NOT NULL);
          INSERT INTO foo VALUES (1, 'BAR!');
        ",
      )
      .await
      .unwrap();
    let id: &str = conn.execute_single("SELECT * FROM foo").await.unwrap().decode(0).unwrap();
    assert_eq!(id, "1");
  }
}