A native PostgreSQL driver for Rust.
Documentation is available at http://sfackler.github.io/rust-postgres/doc/postgres/index.html.
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;
extern crate time;
use time::Timespec;
use postgres::{PostgresConnection, NoSsl};
use postgres::types::ToSql;
struct Person {
id: i32,
name: ~str,
time_created: Timespec,
data: Option<Vec<u8>>
}
fn main() {
let conn = PostgresConnection::connect("postgres://postgres@localhost",
&NoSsl).unwrap();
conn.execute("CREATE TABLE person (
id SERIAL PRIMARY KEY,
name VARCHAR NOT NULL,
time_created TIMESTAMP NOT NULL,
data BYTEA
)", []).unwrap();
let me = Person {
id: 0,
name: "Steven".to_owned(),
time_created: time::get_time(),
data: None
};
conn.execute("INSERT INTO person (name, time_created, data)
VALUES ($1, $2, $3)",
[&me.name as &ToSql, &me.time_created as &ToSql,
&me.data as &ToSql]).unwrap();
let stmt = conn.prepare("SELECT id, name, time_created, data FROM person")
.unwrap();
for row in stmt.query([]).unwrap() {
let person = Person {
id: row[1],
name: row[2],
time_created: row[3],
data: row[4]
};
println!("Found person {}", person.name);
}
}-
Rust - Rust-Postgres is developed against the master branch of the Rust repository. It will most likely not build against the releases on http://www.rust-lang.org.
-
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.
Connect to a Postgres server using the standard URI format:
let conn = try!(PostgresConnection::connect("postgres://user:pass@host:port/database?arg1=val1&arg2=val2",
&NoSsl));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.
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"));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 = conn.prepare("UPDATE foo SET bar = $1 WHERE baz = $2");
let updates = stmt.execute([&1i32 as &ToSql, & &"biz" as &ToSql]);
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. Like statement parameters, result
columns are one-indexed.
let stmt = try!(conn.prepare("SELECT bar, baz FROM foo"));
for row in try!(stmt.query([])) {
let bar: i32 = row[1];
let baz: ~str = row["baz"];
println!("bar: {}, baz: {}", bar, baz);
}In addition, PostgresConnection 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 as &ToSql, & &"biz" as &ToSql]));
println!("{} rows were updated", updates);The transaction method will start a new transaction. It returns a
PostgresTransaction object which has the functionality of a
PostgresConnection 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 a_bad_thing_happened {
trans.set_rollback();
}
if the_coast_is_clear {
trans.set_commit();
}
drop(trans);The transaction will be active until the PostgresTransaction object falls out
of scope. A transaction will commit by default. Nested transactions are
supported via savepoints.
A very basic fixed-size connection pool is provided in the pool module. A
single pool can be shared across tasks and get_connection will block until a
connection is available.
let pool = try!(PostgresConnectionPool::new("postgres://postgres@localhost",
NoSsl, 5));
for _ in range(0, 10) {
let pool = pool.clone();
spawn(proc() {
let conn = pool.get_connection();
conn.query(...).unwrap();
})
}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 |
| i64 | BIGINT, BIGSERIAL |
| f32 | REAL |
| f64 | DOUBLE PRECISION |
| str | VARCHAR, CHAR(n), TEXT |
| [u8]/Vec<u8> | BYTEA |
| extra::json::Json | JSON |
| extra::uuid::Uuid | UUID |
| extra::time::Timespec | TIMESTAMP, TIMESTAMP WITH TIME ZONE |
| types::range::Range<i32> | INT4RANGE |
| types::range::Range<i64> | INT8RANGE |
| types::range::Range<Timespec> | TSRANGE, TSTZRANGE |
| types::array::ArrayBase<Option<bool>> | BOOL[], BOOL[][], ... |
| types::array::ArrayBase<Option<Vec<u8>>> | BYTEA[], BYTEA[][], ... |
| types::array::ArrayBase<Option<i8>> | "char"[], "char"[][], ... |
| types::array::ArrayBase<Option<i16>> | INT2[], INT2[][], ... |
| types::array::ArrayBase<Option<i32>> | INT4[], INT4[][], ... |
| types::array::ArrayBase<Option<~str>> | TEXT[], CHAR(n)[], VARCHAR[], TEXT[][], ... |
| types::array::ArrayBase<Option<Json>> | JSON[], JSON[][], ... |
| types::array::ArrayBase<Option<i64>> | INT8[], INT8[][], ... |
| types::array::ArrayBase<Option<Timespec>> | TIMESTAMP[], TIMESTAMPTZ[], TIMESTAMP[][], ... |
| types::array::ArrayBase<Option<f32>> | FLOAT4[], FLOAT4[][], ... |
| types::array::ArrayBase<Option<f64>> | FLOAT8[], FLOAT8[][], ... |
| types::array::ArrayBase<Option<Uuid>> | UUID[], UUID[][], ... |
| types::array::ArrayBase<Option<Range<i32>>> | INT4RANGE[], INT4RANGE[][], ... |
| types::array::ArrayBase<Option<Range<Timespec>>> | TSRANGE[], TSTZRANGE[], TSRANGE[][], ... |
| types::array::ArrayBase<Option<Range<i64>>> | INT8RANGE[], INT8RANGE[][], ... |
| std::hashmap::HashMap<~str, Option<~str>> | HSTORE |
More conversions can be defined by implementing the ToSql and FromSql
traits.
Like Rust itself, Rust-Postgres is still in the early stages of development, so don't be surprised if APIs change and things break. If something's not working properly, file an issue or submit a pull request!
