Update documentation to focus on direct execution and querying

It's the common case, so make things look simpler to a newcomer.
This commit is contained in:
Steven Fackler
2015-12-06 16:46:06 -08:00
parent 685557aba2
commit 37954d1819
2 changed files with 70 additions and 40 deletions

View File

@@ -68,7 +68,7 @@ fn main() {
Connect to a Postgres server using the standard URI format:
```rust
let conn = try!(Connection::connect("postgres://user:pass@host:port/database?arg1=val1&arg2=val2",
&SslMode::None));
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`,
@@ -77,48 +77,49 @@ defaults to the value of `user` if not specified. The driver supports `trust`,
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.
URLs, the path should be URL encoded. If Postgres stored its socket files in
`/run/postgres`, the connection would then look like:
```rust
let conn = try!(Connection::connect("postgres://postgres@%2Frun%2Fpostgres", &SslMode::None));
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:
```rust
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):
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 `i`th 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):
```rust
let stmt = try!(conn.prepare("UPDATE foo SET bar = $1 WHERE baz = $2"));
let updates = try!(stmt.execute(&[&1i32, &"biz"]));
let updates = try!(conn.execute("UPDATE foo SET bar = $1 WHERE baz = $2", &[&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.
`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.
```rust
let stmt = try!(conn.prepare("SELECT bar, baz FROM foo"));
for row in try!(stmt.query(&[])) {
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);
}
```
In addition, `Connection` has utility `execute` and `query` methods which are
useful if a statement is only going to be executed once:
### Statement Preparation
If the same statement will be executed repeatedly (possibly with different
parameters), explicitly preparing it can improve performance:
```rust
let updates = try!(conn.execute("UPDATE foo SET bar = $1 WHERE baz = $2",
&[&1i32, &"biz"]));
println!("{} rows were updated", updates);
let stmt = try!(conn.prepare("UPDATE foo SET bar = $1 WHERE baz = $2"));
for (bar, baz) in updates {
try!(stmt.update(&[bar, baz]));
}
```
### Transactions

View File

@@ -908,17 +908,33 @@ impl Connection {
InnerConnection::connect(params, ssl).map(|conn| Connection { conn: RefCell::new(conn) })
}
/// A convenience function for queries that are only run once.
/// Executes a statement, returning the number of rows modified.
///
/// If an error is returned, it could have come from either the preparation
/// or execution of the statement.
/// A statement may contain parameters, specified by `$n` where `n` is the
/// index of the parameter in the list provided, 1-indexed.
///
/// On success, returns the number of rows modified or 0 if not applicable.
/// If the statement does not modify any rows (e.g. SELECT), 0 is returned.
///
/// If the same statement will be repeatedly executed (perhaps with
/// different query parameters), consider using the `prepare` and
/// `prepare_cached` methods.
///
/// # Panics
///
/// Panics if the number of parameters provided does not match the number
/// expected.
///
/// # Example
///
/// ```rust,no_run
/// # use postgres::{Connection, SslMode};
/// # let conn = Connection::connect("", SslMode::None).unwrap();
/// # let bar = 1i32;
/// # let baz = true;
/// let rows_updated = conn.execute("UPDATE foo SET bar = $1 WHERE baz = $2", &[&bar, &baz])
/// .unwrap();
/// println!("{} rows updated", rows_updated);
/// ```
pub fn execute(&self, query: &str, params: &[&ToSql]) -> Result<u64> {
let (param_types, columns) = try!(self.conn.borrow_mut().raw_prepare("", query));
let stmt = Statement::new(self,
@@ -930,17 +946,31 @@ impl Connection {
stmt.execute(params)
}
/// A convenience function for queries that are only run once.
/// Executes a statement, returning the resulting rows.
///
/// If an error is returned, it could have come from either the preparation
/// or execution of the statement.
/// A statement may contain parameters, specified by `$n` where `n` is the
/// index of the parameter in the list provided, 1-indexed.
///
/// On success, returns the resulting rows.
/// If the same statement will be repeatedly executed (perhaps with
/// different query parameters), consider using the `prepare` and
/// `prepare_cached` methods.
///
/// ## Panics
/// # Panics
///
/// Panics if the number of parameters provided does not match the number
/// expected.
///
/// # Example
///
/// ```rust,no_run
/// # use postgres::{Connection, SslMode};
/// # let conn = Connection::connect("", SslMode::None).unwrap();
/// # let baz = true;
/// for row in &conn.query("SELECT foo FROM bar WHERE baz = $1", &[&baz]).unwrap() {
/// let foo: i32 = row.get("foo");
/// println!("foo: {}", foo);
/// }
/// ```
pub fn query<'a>(&'a self, query: &str, params: &[&ToSql]) -> Result<Rows<'a>> {
let (param_types, columns) = try!(self.conn.borrow_mut().raw_prepare("", query));
let stmt = Statement::new(self, "".to_owned(), param_types, columns, Cell::new(0), true);
@@ -989,9 +1019,8 @@ impl Connection {
/// Creates a new prepared statement.
///
/// A statement may contain parameters, specified by `$n` where `n` is the
/// index of the parameter in the list provided at execution time,
/// 1-indexed.
/// If the same statement will be executed repeatedly, explicitly preparing
/// it can improve performance.
///
/// The statement is associated with the connection that created it and may
/// not outlive that connection.
@@ -1016,8 +1045,8 @@ impl Connection {
///
/// Like `prepare`, except that the statement is only prepared once over
/// the lifetime of the connection and then cached. If the same statement
/// is going to be used frequently, caching it can improve performance by
/// reducing the number of round trips to the Postgres backend.
/// is going to be prepared frequently, caching it can improve performance
/// by reducing the number of round trips to the Postgres backend.
///
/// # Example
///