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
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/**
 * Represent a set of values, a row of results.
 */
#[derive(Clone, Debug)]
pub struct Tuple<'a> {
    result: &'a libpq::Result,
    index: usize,
}

impl<'a> Tuple<'a> {
    pub(crate) fn from(result: &'a libpq::Result, index: usize) -> Self {
        Self {
            result,
            index,
        }
    }

    /**
     * Retreive the value of field `name` of the tuple.
     *
     * # Panics
     *
     * Panics if `n` is greater than or equal to tuple length.
     */
    pub fn get<T>(&self, name: &str) -> T
    where
        T: crate::FromSql,
    {
        self.try_get(name).unwrap_or_else(|err| {
            panic!("Unable to retreive '{}' field: {}", name, err)
        })
    }

    /**
     * Retreive the value of field `name` of the tuple, or `None` if `n` is
     * greater than or equal to the length of the tuple.
     */
    pub fn try_get<T>(&self, name: &str) -> crate::Result<T>
    where
        T: crate::FromSql,
    {
        let n = match self.result.field_number(name) {
            Some(n) => n,
            None => return Err(crate::Error::MissingField(name.to_string())),
        };

        self.try_nth(n)
    }

    /**
     * Retreive the nth field.
     *
     * # Panics
     *
     * Panics if `n` is greater than or equal to the length of the tuple.
     */
    pub fn nth<T>(&self, n: usize) -> T
    where
        T: crate::FromSql,
    {
        self.try_nth(n).unwrap_or_else(|err| {
            panic!("Unable to retreive field {}: {}", n, err)
        })
    }

    /**
     * Retreive the nth field, or `None` if `n` is greater than or equal to the
     * length of the tuple.
     */
    pub fn try_nth<T>(&self, n: usize) -> crate::Result<T>
    where
        T: crate::FromSql,
    {
        let ty = self.field_type(n);
        let format = self.result.field_format(n);
        let value = self.result.value(self.index, n);

        crate::FromSql::from_sql(&ty, format, value)
    }

    /**
     * Number of field.
     */
    pub fn len(&self) -> usize {
        self.result.nfields()
    }

    /**
     * Is the tuple is empty (doesn’t contain field)?
     */
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /**
     * Retreive the name of field at position `n`, or `None` if `n` is greater
     * than or equal to the length of the tuple.
     */
    pub fn field_name(&self, n: usize) -> Option<String> {
        self.result.field_name(n)
    }

    fn field_type(&self, n: usize) -> crate::pq::Type {
        use std::convert::TryFrom;

        let oid = self.result.field_type(n);

        match crate::pq::Type::try_from(oid) {
            Ok(ty) => ty,
            Err(_) => {
                crate::pq::Type {
                    oid,
                    name: "composite",
                    descr: "Composite type",
                    kind: libpq::types::Kind::Composite,
                }
            },
        }
    }
}