1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
//! Postgres rows.

use postgres_shared::rows::RowData;
use postgres_shared::stmt::Column;
use std::error::Error;
use std::fmt;
use std::sync::Arc;

#[doc(inline)]
pub use postgres_shared::rows::RowIndex;

use RowNew;
use types::{WrongType, FromSql};

/// A row from Postgres.
pub struct Row {
    columns: Arc<Vec<Column>>,
    data: RowData,
}

impl RowNew for Row {
    fn new(columns: Arc<Vec<Column>>, data: RowData) -> Row {
        Row {
            columns: columns,
            data: data,
        }
    }
}

impl Row {
    /// Returns information about the columns in the row.
    pub fn columns(&self) -> &[Column] {
        &self.columns
    }

    /// Returns the number of values in the row
    pub fn len(&self) -> usize {
        self.columns.len()
    }

    /// Retrieves the contents of a field of the row.
    ///
    /// A field can be accessed by the name or index of its column, though
    /// access by index is more efficient. Rows are 0-indexed.
    ///
    /// # Panics
    ///
    /// Panics if the index does not reference a column or the return type is
    /// not compatible with the Postgres type.
    pub fn get<T, I>(&self, idx: I) -> T
        where T: FromSql,
              I: RowIndex + fmt::Debug
    {
        match self.try_get(&idx) {
            Ok(Some(v)) => v,
            Ok(None) => panic!("no such column {:?}", idx),
            Err(e) => panic!("error retrieving row {:?}: {}", idx, e),
        }
    }

    /// Retrieves the contents of a field of the row.
    ///
    /// A field can be accessed by the name or index of its column, though
    /// access by index is more efficient. Rows are 0-indexed.
    ///
    /// Returns `None` if the index does not reference a column, `Some(Err(..))`
    /// if there was an error converting the result value, and `Some(Ok(..))`
    /// on success.
    pub fn try_get<T, I>(&self, idx: I) -> Result<Option<T>, Box<Error + Sync + Send>>
        where T: FromSql,
              I: RowIndex
    {
        let idx = match idx.idx(&self.columns) {
            Some(idx) => idx,
            None => return Ok(None),
        };

        let ty = self.columns[idx].type_();
        if !T::accepts(ty) {
            return Err(Box::new(WrongType::new(ty.clone())));
        }

        T::from_sql_nullable(ty, self.data.get(idx)).map(Some)
    }
}