[][src]Module rocket_contrib::databases

Traits, utilities, and a macro for easy database connection pooling.

Overview

This module provides traits, utilities, and a procedural macro that allows you to easily connect your Rocket application to databases through connection pools. A database connection pool is a data structure that maintains active database connections for later use in the application. This implementation of connection pooling support is based on r2d2 and exposes connections through request guards. Databases are individually configured through Rocket's regular configuration mechanisms: a Rocket.toml file, environment variables, or procedurally.

Connecting your Rocket application to a database using this library occurs in three simple steps:

  1. Configure your databases in Rocket.toml. (see Configuration)
  2. Associate a request guard type and fairing with each database. (see Guard Types)
  3. Use the request guard to retrieve a connection in a handler. (see Handlers)

For a list of supported databases, see Provided Databases. This support can be easily extended by implementing the Poolable trait. See Extending for more.

Example

Before using this library, the feature corresponding to your database type in rocket_contrib must be enabled:

[dependencies.rocket_contrib]
version = "0.4.0-rc.2"
default-features = false
features = ["diesel_sqlite_pool"]

See Provided for a list of supported database and their associated feature name.

In Rocket.toml or the equivalent via environment variables:

[global.databases]
sqlite_logs = { url = "/path/to/database.sqlite" }

In your application's source code, one-time:

#![feature(proc_macro_hygiene, decl_macro)]

#[macro_use] extern crate rocket;
#[macro_use] extern crate rocket_contrib;

use rocket_contrib::databases::diesel;

#[database("sqlite_logs")]
struct LogsDbConn(diesel::SqliteConnection);

fn main() {
    rocket::ignite()
       .attach(LogsDbConn::fairing())
       .launch();
}

Whenever a connection to the database is needed:

#[get("/logs/<id>")]
fn get_logs(conn: LogsDbConn, id: usize) -> Result<Logs> {
    Logs::by_id(&conn, id)
}

Usage

Configuration

Databases can be configured via various mechanisms: Rocket.toml, procedurally via rocket::custom(), or via environment variables.

Rocket.toml

To configure a database via Rocket.toml, add a table for each database to the databases table where the key is a name of your choice. The table should have a url key and, optionally, a pool_size key. This looks as follows:

// Option 1:
[global.databases]
sqlite_db = { url = "db.sqlite" }

// Option 2:
[global.databases.pg_db]
url = "mysql://root:root@localhost/pg_db"

// With a `pool_size` key:
[global.databases]
sqlite_db = { url = "db.sqlite", pool_size = 20 }

The table requires one key:

  • url - the URl to the database

Additionally, all configurations accept the following optional keys:

  • pool_size - the size of the pool, i.e., the number of connections to pool (defaults to the configured number of workers)

Additional options may be required or supported by other adapters.

Procedurally

Databases can also be configured procedurally database via rocket::custom(). The example below does just this:

extern crate rocket;

use std::collections::HashMap;
use rocket::config::{Config, Environment, Value};

fn main() {
    let mut database_config = HashMap::new();
    let mut databases = HashMap::new();

    // This is the same as the following TOML:
    // my_db = { url = "database.sqlite" }
    database_config.insert("url", Value::from("database.sqlite"));
    databases.insert("my_db", Value::from(database_config));

    let config = Config::build(Environment::Development)
        .extra("databases", databases)
        .finalize()
        .unwrap();

    rocket::custom(config).launch();
}

Environment Variables

Lastly, databases can be configured via environment variables by specifying the databases table as detailed in the Environment Variables configuration guide:

ROCKET_DATABASES={my_db={url="db.sqlite"}}

Guard Types

Once a database has been configured, the #[database] attribute can be used to tie a type in your application to a configured database. The database attributes accepts a single string parameter that indicates the name of the database. This corresponds to the database name set as the database's configuration key.

The attribute can only be applied to unit-like structs with one type. The internal type of the structure must implement Poolable.

use rocket_contrib::databases::diesel;

#[database("my_db")]
struct MyDatabase(diesel::SqliteConnection);

The macro generates a FromRequest implementation for the decorated type, allowing the type to be used as a request guard. This implementation retrieves a connection from the database pool or fails with a Status::ServiceUnavailable if no connections are available. The macro also generates an implementation of the Deref trait with the internal Poolable type as the target.

The macro will also generate two inherent methods on the decorated type:

  • fn fairing() -> impl Fairing

    Returns a fairing that initializes the associated database connection pool.

  • fn get_one(&Rocket) -> Option<Self>

    Retrieves a connection from the configured pool. Returns Some as long as Self::fairing() has been attached and there is at least one connection in the pool.

The fairing returned from the generated fairing() method must be attached for the request guard implementation to succeed. Putting the pieces together, a use of the #[database] attribute looks as follows:

use rocket_contrib::databases::diesel;

#[database("my_db")]
struct MyDatabase(diesel::SqliteConnection);

fn main() {
    rocket::custom(config)
        .attach(MyDatabase::fairing())
        .launch();
}

Handlers

Finally, simply use your type as a request guard in a handler to retrieve a connection to a given database:

#[database("my_db")]
struct MyDatabase(diesel::SqliteConnection);

#[get("/")]
fn my_handler(conn: MyDatabase) {
    // ...
}

The generated Deref implementation allows easy access to the inner connection type:

#[database("my_db")]
struct MyDatabase(diesel::SqliteConnection);

fn load_from_db(conn: &diesel::SqliteConnection) -> Data {
    // Do something with connection, return some data.
}

#[get("/")]
fn my_handler(conn: MyDatabase) -> Data {
    load_from_db(&conn)
}

Database Support

Built-in support is provided for many popular databases and drivers. Support can be easily extended by Poolable implementations.

Provided

The list below includes all presently supported database adapters and their corresponding Poolable type.

Kind Driver Poolable Type Feature
MySQL Diesel diesel::MysqlConnection diesel_mysql_pool
MySQL rust-mysql-simple mysql::Conn mysql_pool
Postgres Diesel diesel::PgConnection diesel_postgres_pool
Postgres Rust-Postgres postgres::Connection postgres_pool
Sqlite Diesel diesel::SqliteConnection diesel_sqlite_pool
Sqlite Rustqlite rusqlite::Connection sqlite_pool
Neo4j rusted_cypher rusted_cypher::GraphClient cypher_pool
Redis redis-rs redis::Connection redis_pool

The above table lists all the supported database adapters in this library. In order to use particular Poolable type that's included in this library, you must first enable the feature listed in the "Feature" column. The interior type of your decorated database type should match the type in the "Poolable Type" column.

Extending

Extending Rocket's support to your own custom database adapter (or other database-like struct that can be pooled by r2d2) is as easy as implementing the Poolable trait. See the documentation for Poolable for more details on how to implement it.

Re-exports

pub extern crate r2d2;
pub extern crate diesel;
pub extern crate postgres;
pub extern crate r2d2_postgres;
pub extern crate mysql;
pub extern crate r2d2_mysql;
pub extern crate rusqlite;
pub extern crate r2d2_sqlite;
pub extern crate rusted_cypher;
pub extern crate r2d2_cypher;
pub extern crate redis;
pub extern crate r2d2_redis;

Structs

DatabaseConfig

A structure representing a particular database configuration.

Enums

ConfigError

Error returned on invalid database configurations.

DbError

A wrapper around r2d2::Errors or a custom database error type.

Traits

Poolable

Trait implemented by r2d2-based database adapters.

Functions

database_config

Retrieves the database configuration for the database named name.