Go to file
Steven Fackler 8a0fed9749 Merge pull request #185 from oli-obk/master
address clippy and rust lints
2016-05-30 08:51:13 -07:00
.travis NegotiateSsl implementation for security_framework 2015-12-05 14:35:17 -08:00
benches Optimize execute 2014-12-01 22:24:31 -08:00
codegen Update and fix phf versions 2016-03-29 21:33:48 -07:00
src address comments 2016-05-30 12:50:27 +02:00
tests Merge pull request #184 from nvanbenschoten/nvanbenschoten/savepoints 2016-05-26 21:20:48 -07:00
.gitignore Use persistent codegen for SqlState and Type 2016-02-21 13:30:31 -08:00
.travis.yml Downgrade bitflags to build on 1.7 2016-05-08 19:42:10 -07:00
Cargo.toml Release v0.11.8 2016-05-26 22:58:24 -07:00
LICENSE Bump year in LICENSE 2015-01-07 08:31:00 -08:00
README.md Release v0.11.8 2016-05-26 22:58:24 -07:00
THIRD_PARTY Inline md5 impl 2015-06-09 19:55:28 -07:00

Rust-Postgres

A native PostgreSQL driver for Rust.

Documentation

Build Status Latest Version

You can integrate Rust-Postgres into your project through the releases on crates.io:

# Cargo.toml
[dependencies]
postgres = "0.11"

Overview

Rust-Postgres is a pure-Rust frontend for the popular PostgreSQL database.

extern crate postgres;

use postgres::{Connection, SslMode};

struct Person {
    id: i32,
    name: String,
    data: Option<Vec<u8>>
}

fn main() {
    let conn = Connection::connect("postgres://postgres@localhost", SslMode::None)
            .unwrap();

    conn.execute("CREATE TABLE person (
                    id              SERIAL PRIMARY KEY,
                    name            VARCHAR NOT NULL,
                    data            BYTEA
                  )", &[]).unwrap();
    let me = Person {
        id: 0,
        name: "Steven".to_string(),
        data: None
    };
    conn.execute("INSERT INTO person (name, data) VALUES ($1, $2)",
                 &[&me.name, &me.data]).unwrap();

    for row in &conn.query("SELECT id, name, data FROM person", &[]).unwrap() {
        let person = Person {
            id: row.get(0),
            name: row.get(1),
            data: row.get(2)
        };
        println!("Found person {}", person.name);
    }
}

Requirements

  • Rust - Rust-Postgres is developed against the 1.7 release of Rust available on http://www.rust-lang.org. It should also compile against more recent releases.

  • PostgreSQL 7.4 or later - Rust-Postgres speaks version 3 of the PostgreSQL protocol, which corresponds to versions 7.4 and later. If your version of Postgres was compiled in the last decade, you should be okay.

Usage

Connecting

Connect to a Postgres server using the standard URI format:

let conn = try!(Connection::connect("postgres://user:pass@host:port/database?arg1=val1&arg2=val2",
                                    SslMode::None));

pass may be omitted if not needed. port defaults to 5432 and database defaults to the value of user if not specified. The driver supports trust, password, and md5 authentication.

Unix domain sockets can be used as well by activating the unix_socket or nightly features. The host portion of the URI should be set to the absolute path to the directory containing the socket file. Since / is a reserved character in URLs, the path should be URL encoded. If Postgres stored its socket files in /run/postgres, the connection would then look like:

let conn = try!(Connection::connect("postgres://postgres@%2Frun%2Fpostgres", SslMode::None));

Paths which contain non-UTF8 characters can be handled in a different manner; see the documentation for details.

Querying

SQL statements can be executed with the query and execute methods. Both methods take a query string as well as a slice of parameters to bind to the query. The ith query parameter is specified in the query string by $i. Note that query parameters are 1-indexed rather than the more common 0-indexing.

execute returns the number of rows affected by the query (or 0 if not applicable):

let updates = try!(conn.execute("UPDATE foo SET bar = $1 WHERE baz = $2", &[&1i32, &"biz"]));
println!("{} rows were updated", updates);

query returns an iterable object holding the rows returned from the database. The fields in a row can be accessed either by their indices or their column names, though access by index is more efficient. Unlike statement parameters, result columns are zero-indexed.

for row in &try!(conn.query("SELECT bar, baz FROM foo WHERE buz = $1", &[&1i32])) {
    let bar: i32 = row.get(0);
    let baz: String = row.get("baz");
    println!("bar: {}, baz: {}", bar, baz);
}

Statement Preparation

If the same statement will be executed repeatedly (possibly with different parameters), explicitly preparing it can improve performance:

let stmt = try!(conn.prepare("UPDATE foo SET bar = $1 WHERE baz = $2"));
for (bar, baz) in updates {
    try!(stmt.execute(&[bar, baz]));
}

Transactions

The transaction method will start a new transaction. It returns a Transaction object which has the functionality of a Connection as well as methods to control the result of the transaction:

let trans = try!(conn.transaction());

try!(trans.execute(...));
let stmt = try!(trans.prepare(...));
// ...

try!(trans.commit());

The transaction will be active until the Transaction object falls out of scope. A transaction will roll back by default. Nested transactions are supported via savepoints.

Type Correspondence

Rust-Postgres enforces a strict correspondence between Rust types and Postgres types. The driver currently supports the following conversions:

Rust Type Postgres Type
bool BOOL
i8 "char"
i16 SMALLINT, SMALLSERIAL
i32 INT, SERIAL
u32 OID
i64 BIGINT, BIGSERIAL
f32 REAL
f64 DOUBLE PRECISION
str/String VARCHAR, CHAR(n), TEXT, CITEXT
[u8]/Vec<u8> BYTEA
serialize::json::Json and serde_json::Value (optional) JSON, JSONB
time::Timespec and chrono::NaiveDateTime (optional) TIMESTAMP
time::Timespec, chrono::DateTime<UTC>, chrono::DateTime<Local>, and chrono::DateTime<FixedOffset> (optional) TIMESTAMP WITH TIME ZONE
chrono::NaiveDate (optional) DATE
chrono::NaiveTime (optional) TIME
uuid::Uuid (optional) UUID
bit_vec::BitVec (optional) BIT, VARBIT
HashMap<String, Option<String>> HSTORE
eui48::MacAddress (optional) MACADDR

Option<T> implements FromSql where T: FromSql and ToSql where T: ToSql, and represents nullable Postgres values.

&[T] and Vec<T> implement ToSql where T: ToSql, and Vec<T> additionally implements FromSql where T: FromSql, which represent one-dimensional Postgres arrays.

More conversions can be defined by implementing the ToSql and FromSql traits.

The postgres-derive crate will synthesize ToSql and FromSql implementations for enum, domain, and composite Postgres types.

Full support for array types is located in the postgres-array crate.

Support for range types is located in the postgres-range crate.

Support for the large object API is located in the postgres-large-object crate.

Optional features

Unix socket connections

Support for connections through Unix domain sockets is provided optionally by either the unix_socket or nightly features. It is only available on "unixy" platforms such as OSX, BSD and Linux.

UUID type

UUID support is provided optionally by the uuid feature, which adds ToSql and FromSql implementations for uuid's Uuid type.

JSON/JSONB types

JSON and JSONB support is provided optionally by the rustc-serialize feature, which adds ToSql and FromSql implementations for rustc-serialize's Json type, and the serde_json feature, which adds implementations for serde_json's Value type.

TIMESTAMP/TIMESTAMPTZ/DATE/TIME types

Date and Time support is provided optionally by the time feature, which adds ToSql and FromSql implementations for time's Timespec type, or the chrono feature, which adds ToSql and FromSql implementations for chrono's DateTime, NaiveDateTime, NaiveDate and NaiveTime types.

BIT/VARBIT types

BIT and VARBIT support is provided optionally by the bit-vec feature, which adds ToSql and FromSql implementations for bit-vec's BitVec type.

MACADDR type

MACADDR support is provided optionally by the eui48 feature, which adds ToSql and FromSql implementations for eui48's MacAddress type.