sqlite_tiny/api/
answer.rs

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
//! An SQLite query result

use crate::{
    api::{
        row::Row,
        types::{PointerMut, PointerMutFlex},
    },
    err,
    error::Error,
    ffi, Sqlite,
};

/// A query result
#[derive(Debug)]
pub struct Answer<'db> {
    /// The database
    pub(in crate::api) sqlite: &'db Sqlite,
    /// The statement
    pub(in crate::api) raw: PointerMut<ffi::sqlite3_stmt>,
    /// If we already have a fetched row pending
    pub(in crate::api) has_row: bool,
}
impl Answer<'_> {
    /// Gets the current pending result row or returns an error if there is no row
    pub fn row(mut self) -> Result<Row<'static>, Error> {
        // Try to fetch the next row if necessary
        if !self.has_row {
            // Do a step to get the next row if any
            self.step()?;
        }

        // Check if we have a row now
        if !self.has_row {
            // We still don't have a row
            return Err(err!("No result row available"));
        }

        // Return an borrowed row
        let row = Row { raw: PointerMutFlex::Owned(self.raw) };
        Ok(row)
    }

    /// Returns the next row like a fallible iterator
    pub fn next_row(&mut self) -> Result<Option<Row>, Error> {
        // Try to fetch the next row if necessary
        if !self.has_row {
            // Do a step to get the next row if any
            self.step()?;
        }

        // Check if we have a row now
        if !self.has_row {
            // We still don't have a row
            return Ok(None);
        }

        // Return an borrowed row
        let row = Row { raw: PointerMutFlex::Borrowed(&mut self.raw) };
        self.has_row = false;
        Ok(Some(row))
    }

    /// Advances the underlying statement towards the first or subsequent row
    pub(in crate::api) fn step(&mut self) -> Result<(), Error> {
        // Do a step
        let retval = unsafe { ffi::sqlite3_step(self.raw.as_ptr()) };
        let true = matches!(retval, ffi::SQLITE_ROW | ffi::SQLITE_DONE) else {
            // Failed while trying to get the next row
            return Err(unsafe { ffi::sqlite3_last_error(retval, self.sqlite.raw.as_ptr()) });
        };

        // Mark if we have a pending row
        self.has_row = retval == ffi::SQLITE_ROW;
        Ok(())
    }
}