Zero-index ResultRow

It seems like this is the decision made by every DB interface *except*
JDBC, and is more consistent with the rest of the language anyway.

Closes #42.
This commit is contained in:
Steven Fackler 2014-06-29 22:53:03 -07:00
parent a54fdaf834
commit 8b74cb0ab4
3 changed files with 34 additions and 34 deletions

View File

@ -52,10 +52,10 @@ fn main() {
.unwrap(); .unwrap();
for row in stmt.query([]).unwrap() { for row in stmt.query([]).unwrap() {
let person = Person { let person = Person {
id: row[1u], id: row[0u],
name: row[2u], name: row[1u],
time_created: row[3u], time_created: row[2u],
data: row[4u] data: row[3u]
}; };
println!("Found person {}", person.name); println!("Found person {}", person.name);
} }
@ -117,12 +117,12 @@ println!("{} rows were updated", updates);
``` ```
`query` returns an iterator over the rows returned from the database. The `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, 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 though access by index is more efficient. Unlike statement parameters, result
columns are one-indexed. columns are zero-indexed.
```rust ```rust
let stmt = try!(conn.prepare("SELECT bar, baz FROM foo")); let stmt = try!(conn.prepare("SELECT bar, baz FROM foo"));
for row in try!(stmt.query([])) { for row in try!(stmt.query([])) {
let bar: i32 = row[1u]; let bar: i32 = row[0u];
let baz: String = row["baz"]; let baz: String = row["baz"];
println!("bar: {}, baz: {}", bar, baz); println!("bar: {}, baz: {}", bar, baz);
} }

View File

@ -44,10 +44,10 @@ fn main() {
.unwrap(); .unwrap();
for row in stmt.query([]).unwrap() { for row in stmt.query([]).unwrap() {
let person = Person { let person = Person {
id: row[1u], id: row[0u],
name: row[2u], name: row[1u],
time_created: row[3u], time_created: row[2u],
data: row[4u] data: row[3u]
}; };
println!("Found person {}", person.name); println!("Found person {}", person.name);
} }
@ -1452,7 +1452,7 @@ impl<'stmt, I: RowIndex+Clone+fmt::Show, T: FromSql> Index<I, T>
/// Retreives the contents of a field of the row. /// Retreives the contents of a field of the row.
/// ///
/// A field can be accessed by the name or index of its column, though /// A field can be accessed by the name or index of its column, though
/// access by index is more efficient. Rows are 1-indexed. /// access by index is more efficient. Rows are 0-indexed.
/// ///
/// # Failure /// # Failure
/// ///
@ -1467,7 +1467,7 @@ impl<'stmt, I: RowIndex+Clone+fmt::Show, T: FromSql> Index<I, T>
/// # let stmt = conn.prepare("").unwrap(); /// # let stmt = conn.prepare("").unwrap();
/// # let mut result = stmt.query([]).unwrap(); /// # let mut result = stmt.query([]).unwrap();
/// # let row = result.next().unwrap(); /// # let row = result.next().unwrap();
/// let foo: i32 = row[1u]; /// let foo: i32 = row[0u];
/// let bar: String = row["bar"]; /// let bar: String = row["bar"];
/// ``` /// ```
fn index(&self, idx: &I) -> T { fn index(&self, idx: &I) -> T {
@ -1488,10 +1488,10 @@ pub trait RowIndex {
impl RowIndex for uint { impl RowIndex for uint {
#[inline] #[inline]
fn idx(&self, stmt: &PostgresStatement) -> Option<uint> { fn idx(&self, stmt: &PostgresStatement) -> Option<uint> {
if *self == 0 || *self > stmt.result_desc.len() { if *self > stmt.result_desc.len() {
None None
} else { } else {
Some(*self - 1) Some(*self)
} }
} }
} }

View File

@ -116,7 +116,7 @@ fn test_unix_connection() {
let conn = or_fail!(PostgresConnection::connect("postgres://postgres@localhost", &NoSsl)); let conn = or_fail!(PostgresConnection::connect("postgres://postgres@localhost", &NoSsl));
let stmt = or_fail!(conn.prepare("SHOW unix_socket_directories")); let stmt = or_fail!(conn.prepare("SHOW unix_socket_directories"));
let result = or_fail!(stmt.query([])); let result = or_fail!(stmt.query([]));
let unix_socket_directories: String = result.map(|row| row[1u]).next().unwrap(); let unix_socket_directories: String = result.map(|row| row[0u]).next().unwrap();
if unix_socket_directories.is_empty() { if unix_socket_directories.is_empty() {
fail!("can't test connect_unix; unix_socket_directories is empty"); fail!("can't test connect_unix; unix_socket_directories is empty");
@ -142,7 +142,7 @@ fn test_transaction_commit() {
let stmt = or_fail!(conn.prepare("SELECT * FROM foo")); let stmt = or_fail!(conn.prepare("SELECT * FROM foo"));
let result = or_fail!(stmt.query([])); let result = or_fail!(stmt.query([]));
assert_eq!(vec![1i32], result.map(|row| row[1u]).collect()); assert_eq!(vec![1i32], result.map(|row| row[0u]).collect());
} }
#[test] #[test]
@ -157,7 +157,7 @@ fn test_transaction_commit_finish() {
let stmt = or_fail!(conn.prepare("SELECT * FROM foo")); let stmt = or_fail!(conn.prepare("SELECT * FROM foo"));
let result = or_fail!(stmt.query([])); let result = or_fail!(stmt.query([]));
assert_eq!(vec![1i32], result.map(|row| row[1u]).collect()); assert_eq!(vec![1i32], result.map(|row| row[0u]).collect());
} }
#[test] #[test]
@ -175,7 +175,7 @@ fn test_transaction_rollback() {
let stmt = or_fail!(conn.prepare("SELECT * FROM foo")); let stmt = or_fail!(conn.prepare("SELECT * FROM foo"));
let result = or_fail!(stmt.query([])); let result = or_fail!(stmt.query([]));
assert_eq!(vec![1i32], result.map(|row| row[1u]).collect()); assert_eq!(vec![1i32], result.map(|row| row[0u]).collect());
} }
#[test] #[test]
@ -193,7 +193,7 @@ fn test_transaction_rollback_finish() {
let stmt = or_fail!(conn.prepare("SELECT * FROM foo")); let stmt = or_fail!(conn.prepare("SELECT * FROM foo"));
let result = or_fail!(stmt.query([])); let result = or_fail!(stmt.query([]));
assert_eq!(vec![1i32], result.map(|row| row[1u]).collect()); assert_eq!(vec![1i32], result.map(|row| row[0u]).collect());
} }
#[test] #[test]
@ -232,7 +232,7 @@ fn test_nested_transactions() {
let stmt = or_fail!(trans1.prepare("SELECT * FROM foo ORDER BY id")); let stmt = or_fail!(trans1.prepare("SELECT * FROM foo ORDER BY id"));
let result = or_fail!(stmt.query([])); let result = or_fail!(stmt.query([]));
assert_eq!(vec![1i32, 2, 4, 6], result.map(|row| row[1u]).collect()); assert_eq!(vec![1i32, 2, 4, 6], result.map(|row| row[0u]).collect());
trans1.set_rollback(); trans1.set_rollback();
} }
@ -240,7 +240,7 @@ fn test_nested_transactions() {
let stmt = or_fail!(conn.prepare("SELECT * FROM foo ORDER BY id")); let stmt = or_fail!(conn.prepare("SELECT * FROM foo ORDER BY id"));
let result = or_fail!(stmt.query([])); let result = or_fail!(stmt.query([]));
assert_eq!(vec![1i32], result.map(|row| row[1u]).collect()); assert_eq!(vec![1i32], result.map(|row| row[0u]).collect());
} }
#[test] #[test]
@ -286,7 +286,7 @@ fn test_nested_transactions_finish() {
let stmt = or_fail!(trans1.prepare("SELECT * FROM foo ORDER BY id")); let stmt = or_fail!(trans1.prepare("SELECT * FROM foo ORDER BY id"));
let result = or_fail!(stmt.query([])); let result = or_fail!(stmt.query([]));
assert_eq!(vec![1i32, 2, 4, 6], result.map(|row| row[1u]).collect()); assert_eq!(vec![1i32, 2, 4, 6], result.map(|row| row[0u]).collect());
} }
trans1.set_rollback(); trans1.set_rollback();
@ -296,7 +296,7 @@ fn test_nested_transactions_finish() {
let stmt = or_fail!(conn.prepare("SELECT * FROM foo ORDER BY id")); let stmt = or_fail!(conn.prepare("SELECT * FROM foo ORDER BY id"));
let result = or_fail!(stmt.query([])); let result = or_fail!(stmt.query([]));
assert_eq!(vec![1i32], result.map(|row| row[1u]).collect()); assert_eq!(vec![1i32], result.map(|row| row[0u]).collect());
} }
#[test] #[test]
@ -350,7 +350,7 @@ fn test_batch_execute() {
let stmt = or_fail!(conn.prepare("SELECT * from foo ORDER BY id")); let stmt = or_fail!(conn.prepare("SELECT * from foo ORDER BY id"));
let result = or_fail!(stmt.query([])); let result = or_fail!(stmt.query([]));
assert_eq!(vec![10i64], result.map(|row| row[1u]).collect()); assert_eq!(vec![10i64], result.map(|row| row[0u]).collect());
} }
#[test] #[test]
@ -378,7 +378,7 @@ fn test_query() {
let stmt = or_fail!(conn.prepare("SELECT * from foo ORDER BY id")); let stmt = or_fail!(conn.prepare("SELECT * from foo ORDER BY id"));
let result = or_fail!(stmt.query([])); let result = or_fail!(stmt.query([]));
assert_eq!(vec![1i64, 2], result.map(|row| row[1u]).collect()); assert_eq!(vec![1i64, 2], result.map(|row| row[0u]).collect());
} }
#[test] #[test]
@ -403,7 +403,7 @@ fn test_lazy_query() {
} }
let stmt = or_fail!(trans.prepare("SELECT id FROM foo ORDER BY id")); let stmt = or_fail!(trans.prepare("SELECT id FROM foo ORDER BY id"));
let result = or_fail!(trans.lazy_query(&stmt, [], 2)); let result = or_fail!(trans.lazy_query(&stmt, [], 2));
assert_eq!(values, result.map(|row| row.unwrap()[1u]).collect()); assert_eq!(values, result.map(|row| row.unwrap()[0u]).collect());
trans.set_rollback(); trans.set_rollback();
} }
@ -455,11 +455,11 @@ fn test_type<T: PartialEq+FromSql+ToSql, S: Str>(sql_type: &str, checks: &[(T, S
let conn = or_fail!(PostgresConnection::connect("postgres://postgres@localhost", &NoSsl)); let conn = or_fail!(PostgresConnection::connect("postgres://postgres@localhost", &NoSsl));
for &(ref val, ref repr) in checks.iter() { for &(ref val, ref repr) in checks.iter() {
let stmt = or_fail!(conn.prepare(format!("SELECT {:s}::{}", *repr, sql_type).as_slice())); let stmt = or_fail!(conn.prepare(format!("SELECT {:s}::{}", *repr, sql_type).as_slice()));
let result = or_fail!(stmt.query([])).next().unwrap()[1u]; let result = or_fail!(stmt.query([])).next().unwrap()[0u];
assert!(val == &result); assert!(val == &result);
let stmt = or_fail!(conn.prepare(format!("SELECT $1::{}", sql_type).as_slice())); let stmt = or_fail!(conn.prepare(format!("SELECT $1::{}", sql_type).as_slice()));
let result = or_fail!(stmt.query([val as &ToSql])).next().unwrap()[1u]; let result = or_fail!(stmt.query([val as &ToSql])).next().unwrap()[0u];
assert!(val == &result); assert!(val == &result);
} }
} }
@ -544,7 +544,7 @@ fn test_bpchar_params() {
let res = or_fail!(stmt.query([])); let res = or_fail!(stmt.query([]));
assert_eq!(vec!(Some("12345".to_str()), Some("123 ".to_str()), None), assert_eq!(vec!(Some("12345".to_str()), Some("123 ".to_str()), None),
res.map(|row| row[1u]).collect()); res.map(|row| row[0u]).collect());
} }
#[test] #[test]
@ -795,13 +795,13 @@ fn test_nan_param<T: Float+ToSql+FromSql>(sql_type: &str) {
let conn = or_fail!(PostgresConnection::connect("postgres://postgres@localhost", &NoSsl)); let conn = or_fail!(PostgresConnection::connect("postgres://postgres@localhost", &NoSsl));
let stmt = or_fail!(conn.prepare(format!("SELECT 'NaN'::{}", sql_type).as_slice())); let stmt = or_fail!(conn.prepare(format!("SELECT 'NaN'::{}", sql_type).as_slice()));
let mut result = or_fail!(stmt.query([])); let mut result = or_fail!(stmt.query([]));
let val: T = result.next().unwrap()[1u]; let val: T = result.next().unwrap()[0u];
assert!(val.is_nan()); assert!(val.is_nan());
let nan: T = Float::nan(); let nan: T = Float::nan();
let stmt = or_fail!(conn.prepare(format!("SELECT $1::{}", sql_type).as_slice())); let stmt = or_fail!(conn.prepare(format!("SELECT $1::{}", sql_type).as_slice()));
let mut result = or_fail!(stmt.query([&nan as &ToSql])); let mut result = or_fail!(stmt.query([&nan as &ToSql]));
let val: T = result.next().unwrap()[1u]; let val: T = result.next().unwrap()[0u];
assert!(val.is_nan()) assert!(val.is_nan())
} }
@ -881,7 +881,7 @@ fn test_get_was_null() {
let stmt = or_fail!(conn.prepare("SELECT NULL::INT as id")); let stmt = or_fail!(conn.prepare("SELECT NULL::INT as id"));
let mut result = or_fail!(stmt.query([])); let mut result = or_fail!(stmt.query([]));
match result.next().unwrap().get::<uint, i32>(1) { match result.next().unwrap().get::<uint, i32>(0) {
Err(PgWasNull) => {} Err(PgWasNull) => {}
res => fail!("unexpected result {}", res), res => fail!("unexpected result {}", res),
}; };
@ -1061,6 +1061,6 @@ fn test_pg_database_datname() {
let mut result = or_fail!(stmt.query([])); let mut result = or_fail!(stmt.query([]));
let next = result.next().unwrap(); let next = result.next().unwrap();
or_fail!(next.get::<uint, String>(1)); or_fail!(next.get::<uint, String>(0));
or_fail!(next.get::<&str, String>("datname")); or_fail!(next.get::<&str, String>("datname"));
} }