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
use super::result::PgResult;
use crate::pg::value::TypeOidLookup;
use crate::pg::{Pg, PgValue};
use crate::row::*;
use std::rc::Rc;

#[derive(Clone)]
#[allow(missing_debug_implementations)]
pub struct PgRow {
    db_result: Rc<PgResult>,
    row_idx: usize,
}

impl PgRow {
    pub(crate) fn new(db_result: Rc<PgResult>, row_idx: usize) -> Self {
        PgRow { db_result, row_idx }
    }
}

impl<'a> RowGatWorkaround<'a, Pg> for PgRow {
    type Field = PgField<'a>;
}

impl<'a> Row<'a, Pg> for PgRow {
    type InnerPartialRow = Self;

    fn field_count(&self) -> usize {
        self.db_result.column_count()
    }

    fn get<'b, I>(&'b self, idx: I) -> Option<<Self as RowGatWorkaround<'b, Pg>>::Field>
    where
        'a: 'b,
        Self: RowIndex<I>,
    {
        let idx = self.idx(idx)?;
        Some(PgField {
            db_result: &self.db_result,
            row_idx: self.row_idx,
            col_idx: idx,
        })
    }

    fn partial_row(&self, range: std::ops::Range<usize>) -> PartialRow<'_, Self::InnerPartialRow> {
        PartialRow::new(self, range)
    }
}

impl RowIndex<usize> for PgRow {
    fn idx(&self, idx: usize) -> Option<usize> {
        if idx < self.field_count() {
            Some(idx)
        } else {
            None
        }
    }
}

impl<'a> RowIndex<&'a str> for PgRow {
    fn idx(&self, field_name: &'a str) -> Option<usize> {
        (0..self.field_count()).find(|idx| self.db_result.column_name(*idx) == Some(field_name))
    }
}

#[allow(missing_debug_implementations)]
pub struct PgField<'a> {
    db_result: &'a PgResult,
    row_idx: usize,
    col_idx: usize,
}

impl<'a> Field<'a, Pg> for PgField<'a> {
    fn field_name(&self) -> Option<&str> {
        self.db_result.column_name(self.col_idx)
    }

    fn value(&self) -> Option<crate::backend::RawValue<'_, Pg>> {
        let raw = self.db_result.get(self.row_idx, self.col_idx)?;

        Some(PgValue::new_internal(raw, self))
    }
}

impl<'a> TypeOidLookup for PgField<'a> {
    fn lookup(&self) -> std::num::NonZeroU32 {
        self.db_result.column_type(self.col_idx)
    }
}