From 37954d1819925e6a24b22bbfbdd62393f0548003 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 6 Dec 2015 16:46:06 -0800 Subject: [PATCH] Update documentation to focus on direct execution and querying It's the common case, so make things look simpler to a newcomer. --- README.md | 53 +++++++++++++++++++++++++------------------------- src/lib.rs | 57 ++++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 70 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 176f1ea5..2086ce3b 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/src/lib.rs b/src/lib.rs index 135cce9a..293e8ad5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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 { 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> { 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 ///