Go to file
2015-05-16 18:58:13 -07:00
.travis Deploy master docs to master folder 2015-05-16 15:01:24 -07:00
benches Optimize execute 2014-12-01 22:24:31 -08:00
src Deploy master docs to master folder 2015-05-16 15:01:24 -07:00
tests Add optional chrono support 2015-05-13 22:25:43 -07:00
.gitattributes Force Linux line endings for Rust files 2014-05-18 21:36:04 -07:00
.gitignore Remove old gitignore line 2015-04-01 00:07:11 -07:00
.travis.yml Test chrono support 2015-05-13 22:26:05 -07:00
build.rs Fix for upstream changes 2015-04-02 11:34:42 -07:00
Cargo.toml Merge branch 'release' 2015-05-16 18:58:13 -07:00
LICENSE Bump year in LICENSE 2015-01-07 08:31:00 -08:00
README.md Fix README URL 2015-05-16 15:01:42 -07:00
THIRD_PARTY Pull liburl in-crate 2014-10-15 08:37:43 -07:00

Rust-Postgres

A native PostgreSQL driver for Rust.

Documentation is available at https://sfackler.github.io/rust-postgres/doc/master/postgres

Build Status Latest Version

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

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

Overview

Rust-Postgres is a pure-Rust frontend for the popular PostgreSQL database. It exposes a high level interface in the vein of JDBC or Go's database/sql package.

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();

    let stmt = conn.prepare("SELECT id, name, data FROM person").unwrap();
    for row in stmt.query(&[]).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.0.0 beta release of Rust available on http://www.rust-lang.org. It should also compile against more recent unstable 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 feature. 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.

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.

Statement Preparation

Prepared statements can have parameters, represented as $n where n is an index into the parameter array starting from 1:

let stmt = try!(conn.prepare("SELECT * FROM foo WHERE bar = $1 AND baz = $2"));

Querying

A prepared statement can be executed with the query and execute methods. Both methods take an array of parameters to bind to the query represented as &ToSql trait objects. execute returns the number of rows affected by the query (or 0 if not applicable):

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

query returns an iterator over 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.

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

In addition, Connection has a utility execute method which is useful if a statement is only going to be executed once:

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

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(...));

if the_coast_is_clear {
    trans.set_commit();
}

try!(trans.finish());

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 and chrono::DateTime<UTC> (optional) TIMESTAMP WITH TIME ZONE
chrono::NaiveDate (optional) DATE
chrono::NaiveTime (optional) TIME
uuid::Uuid (optional) UUID
HashMap<String, Option<String>> HSTORE

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

Support for Postgres arrays is located in the postgres-array crate.

Support for Postgres ranges is located in the postgres-range crate.

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

Optional features

Unix socket connections

Support for connections through Unix domain sockets is provided optionally by the unix_socket feature. 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 feature, which adds implementations for serde's json::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.