sqlx_sqlite/connection/
execute.rs

1use crate::connection::{ConnectionHandle, ConnectionState};
2use crate::error::Error;
3use crate::logger::QueryLogger;
4use crate::statement::{StatementHandle, VirtualStatement};
5use crate::{SqliteArguments, SqliteQueryResult, SqliteRow};
6use sqlx_core::Either;
7
8pub struct ExecuteIter<'a> {
9    handle: &'a mut ConnectionHandle,
10    statement: &'a mut VirtualStatement,
11    logger: QueryLogger<'a>,
12    args: Option<SqliteArguments<'a>>,
13
14    /// since a `VirtualStatement` can encompass multiple actual statements,
15    /// this keeps track of the number of arguments so far
16    args_used: usize,
17
18    goto_next: bool,
19}
20
21pub(crate) fn iter<'a>(
22    conn: &'a mut ConnectionState,
23    query: &'a str,
24    args: Option<SqliteArguments<'a>>,
25    persistent: bool,
26) -> Result<ExecuteIter<'a>, Error> {
27    // fetch the cached statement or allocate a new one
28    let statement = conn.statements.get(query, persistent)?;
29
30    let logger = QueryLogger::new(query, conn.log_settings.clone());
31
32    Ok(ExecuteIter {
33        handle: &mut conn.handle,
34        statement,
35        logger,
36        args,
37        args_used: 0,
38        goto_next: true,
39    })
40}
41
42fn bind(
43    statement: &mut StatementHandle,
44    arguments: &Option<SqliteArguments<'_>>,
45    offset: usize,
46) -> Result<usize, Error> {
47    let mut n = 0;
48
49    if let Some(arguments) = arguments {
50        n = arguments.bind(statement, offset)?;
51    }
52
53    Ok(n)
54}
55
56impl ExecuteIter<'_> {
57    pub fn finish(&mut self) -> Result<(), Error> {
58        for res in self {
59            let _ = res?;
60        }
61
62        Ok(())
63    }
64}
65
66impl Iterator for ExecuteIter<'_> {
67    type Item = Result<Either<SqliteQueryResult, SqliteRow>, Error>;
68
69    fn next(&mut self) -> Option<Self::Item> {
70        let statement = if self.goto_next {
71            let statement = match self.statement.prepare_next(self.handle) {
72                Ok(Some(statement)) => statement,
73                Ok(None) => return None,
74                Err(e) => return Some(Err(e)),
75            };
76
77            self.goto_next = false;
78
79            // sanity check: ensure the VM is reset and the bindings are cleared
80            if let Err(e) = statement.handle.reset() {
81                return Some(Err(e.into()));
82            }
83
84            statement.handle.clear_bindings();
85
86            match bind(statement.handle, &self.args, self.args_used) {
87                Ok(args_used) => self.args_used += args_used,
88                Err(e) => return Some(Err(e)),
89            }
90
91            statement
92        } else {
93            self.statement.current()?
94        };
95
96        match statement.handle.step() {
97            Ok(true) => {
98                self.logger.increment_rows_returned();
99
100                Some(Ok(Either::Right(SqliteRow::current(
101                    statement.handle,
102                    statement.columns,
103                    statement.column_names,
104                ))))
105            }
106            Ok(false) => {
107                let last_insert_rowid = self.handle.last_insert_rowid();
108
109                let changes = statement.handle.changes();
110                self.logger.increase_rows_affected(changes);
111
112                let done = SqliteQueryResult {
113                    changes,
114                    last_insert_rowid,
115                };
116
117                self.goto_next = true;
118
119                Some(Ok(Either::Left(done)))
120            }
121            Err(e) => Some(Err(e.into())),
122        }
123    }
124}
125
126impl Drop for ExecuteIter<'_> {
127    fn drop(&mut self) {
128        self.statement.reset().ok();
129    }
130}