1 //! Run-Time Limits
2 
3 use crate::{ffi, Connection};
4 use std::os::raw::c_int;
5 
6 /// Run-Time limit categories, for use with [`Connection::limit`] and
7 /// [`Connection::set_limit`].
8 ///
9 /// See the official documentation for more information:
10 /// - <https://www.sqlite.org/c3ref/c_limit_attached.html>
11 /// - <https://www.sqlite.org/limits.html>
12 #[repr(i32)]
13 #[non_exhaustive]
14 #[allow(clippy::upper_case_acronyms, non_camel_case_types)]
15 #[cfg_attr(docsrs, doc(cfg(feature = "limits")))]
16 pub enum Limit {
17     /// The maximum size of any string or BLOB or table row, in bytes.
18     SQLITE_LIMIT_LENGTH = ffi::SQLITE_LIMIT_LENGTH,
19     /// The maximum length of an SQL statement, in bytes.
20     SQLITE_LIMIT_SQL_LENGTH = ffi::SQLITE_LIMIT_SQL_LENGTH,
21     /// The maximum number of columns in a table definition or in the result set
22     /// of a SELECT or the maximum number of columns in an index or in an
23     /// ORDER BY or GROUP BY clause.
24     SQLITE_LIMIT_COLUMN = ffi::SQLITE_LIMIT_COLUMN,
25     /// The maximum depth of the parse tree on any expression.
26     SQLITE_LIMIT_EXPR_DEPTH = ffi::SQLITE_LIMIT_EXPR_DEPTH,
27     /// The maximum number of terms in a compound SELECT statement.
28     SQLITE_LIMIT_COMPOUND_SELECT = ffi::SQLITE_LIMIT_COMPOUND_SELECT,
29     /// The maximum number of instructions in a virtual machine program used to
30     /// implement an SQL statement.
31     SQLITE_LIMIT_VDBE_OP = ffi::SQLITE_LIMIT_VDBE_OP,
32     /// The maximum number of arguments on a function.
33     SQLITE_LIMIT_FUNCTION_ARG = ffi::SQLITE_LIMIT_FUNCTION_ARG,
34     /// The maximum number of attached databases.
35     SQLITE_LIMIT_ATTACHED = ffi::SQLITE_LIMIT_ATTACHED,
36     /// The maximum length of the pattern argument to the LIKE or GLOB
37     /// operators.
38     SQLITE_LIMIT_LIKE_PATTERN_LENGTH = ffi::SQLITE_LIMIT_LIKE_PATTERN_LENGTH,
39     /// The maximum index number of any parameter in an SQL statement.
40     SQLITE_LIMIT_VARIABLE_NUMBER = ffi::SQLITE_LIMIT_VARIABLE_NUMBER,
41     /// The maximum depth of recursion for triggers.
42     SQLITE_LIMIT_TRIGGER_DEPTH = ffi::SQLITE_LIMIT_TRIGGER_DEPTH,
43     /// The maximum number of auxiliary worker threads that a single prepared
44     /// statement may start.
45     SQLITE_LIMIT_WORKER_THREADS = ffi::SQLITE_LIMIT_WORKER_THREADS,
46 }
47 
48 impl Connection {
49     /// Returns the current value of a [`Limit`].
50     #[inline]
51     #[cfg_attr(docsrs, doc(cfg(feature = "limits")))]
limit(&self, limit: Limit) -> i3252     pub fn limit(&self, limit: Limit) -> i32 {
53         let c = self.db.borrow();
54         unsafe { ffi::sqlite3_limit(c.db(), limit as c_int, -1) }
55     }
56 
57     /// Changes the [`Limit`] to `new_val`, returning the prior
58     /// value of the limit.
59     #[inline]
60     #[cfg_attr(docsrs, doc(cfg(feature = "limits")))]
set_limit(&self, limit: Limit, new_val: i32) -> i3261     pub fn set_limit(&self, limit: Limit, new_val: i32) -> i32 {
62         let c = self.db.borrow_mut();
63         unsafe { ffi::sqlite3_limit(c.db(), limit as c_int, new_val) }
64     }
65 }
66 
67 #[cfg(test)]
68 mod test {
69     use super::*;
70     use crate::{Connection, Result};
71 
72     #[test]
test_limit_values()73     fn test_limit_values() {
74         assert_eq!(Limit::SQLITE_LIMIT_LENGTH as i32, ffi::SQLITE_LIMIT_LENGTH,);
75         assert_eq!(
76             Limit::SQLITE_LIMIT_SQL_LENGTH as i32,
77             ffi::SQLITE_LIMIT_SQL_LENGTH,
78         );
79         assert_eq!(Limit::SQLITE_LIMIT_COLUMN as i32, ffi::SQLITE_LIMIT_COLUMN,);
80         assert_eq!(
81             Limit::SQLITE_LIMIT_EXPR_DEPTH as i32,
82             ffi::SQLITE_LIMIT_EXPR_DEPTH,
83         );
84         assert_eq!(
85             Limit::SQLITE_LIMIT_COMPOUND_SELECT as i32,
86             ffi::SQLITE_LIMIT_COMPOUND_SELECT,
87         );
88         assert_eq!(
89             Limit::SQLITE_LIMIT_VDBE_OP as i32,
90             ffi::SQLITE_LIMIT_VDBE_OP,
91         );
92         assert_eq!(
93             Limit::SQLITE_LIMIT_FUNCTION_ARG as i32,
94             ffi::SQLITE_LIMIT_FUNCTION_ARG,
95         );
96         assert_eq!(
97             Limit::SQLITE_LIMIT_ATTACHED as i32,
98             ffi::SQLITE_LIMIT_ATTACHED,
99         );
100         assert_eq!(
101             Limit::SQLITE_LIMIT_LIKE_PATTERN_LENGTH as i32,
102             ffi::SQLITE_LIMIT_LIKE_PATTERN_LENGTH,
103         );
104         assert_eq!(
105             Limit::SQLITE_LIMIT_VARIABLE_NUMBER as i32,
106             ffi::SQLITE_LIMIT_VARIABLE_NUMBER,
107         );
108         #[cfg(feature = "bundled")]
109         assert_eq!(
110             Limit::SQLITE_LIMIT_TRIGGER_DEPTH as i32,
111             ffi::SQLITE_LIMIT_TRIGGER_DEPTH,
112         );
113         #[cfg(feature = "bundled")]
114         assert_eq!(
115             Limit::SQLITE_LIMIT_WORKER_THREADS as i32,
116             ffi::SQLITE_LIMIT_WORKER_THREADS,
117         );
118     }
119 
120     #[test]
test_limit() -> Result<()>121     fn test_limit() -> Result<()> {
122         let db = Connection::open_in_memory()?;
123         db.set_limit(Limit::SQLITE_LIMIT_LENGTH, 1024);
124         assert_eq!(1024, db.limit(Limit::SQLITE_LIMIT_LENGTH));
125 
126         db.set_limit(Limit::SQLITE_LIMIT_SQL_LENGTH, 1024);
127         assert_eq!(1024, db.limit(Limit::SQLITE_LIMIT_SQL_LENGTH));
128 
129         db.set_limit(Limit::SQLITE_LIMIT_COLUMN, 64);
130         assert_eq!(64, db.limit(Limit::SQLITE_LIMIT_COLUMN));
131 
132         db.set_limit(Limit::SQLITE_LIMIT_EXPR_DEPTH, 256);
133         assert_eq!(256, db.limit(Limit::SQLITE_LIMIT_EXPR_DEPTH));
134 
135         db.set_limit(Limit::SQLITE_LIMIT_COMPOUND_SELECT, 32);
136         assert_eq!(32, db.limit(Limit::SQLITE_LIMIT_COMPOUND_SELECT));
137 
138         db.set_limit(Limit::SQLITE_LIMIT_FUNCTION_ARG, 32);
139         assert_eq!(32, db.limit(Limit::SQLITE_LIMIT_FUNCTION_ARG));
140 
141         db.set_limit(Limit::SQLITE_LIMIT_ATTACHED, 2);
142         assert_eq!(2, db.limit(Limit::SQLITE_LIMIT_ATTACHED));
143 
144         db.set_limit(Limit::SQLITE_LIMIT_LIKE_PATTERN_LENGTH, 128);
145         assert_eq!(128, db.limit(Limit::SQLITE_LIMIT_LIKE_PATTERN_LENGTH));
146 
147         db.set_limit(Limit::SQLITE_LIMIT_VARIABLE_NUMBER, 99);
148         assert_eq!(99, db.limit(Limit::SQLITE_LIMIT_VARIABLE_NUMBER));
149 
150         // SQLITE_LIMIT_TRIGGER_DEPTH was added in SQLite 3.6.18.
151         if crate::version_number() >= 3_006_018 {
152             db.set_limit(Limit::SQLITE_LIMIT_TRIGGER_DEPTH, 32);
153             assert_eq!(32, db.limit(Limit::SQLITE_LIMIT_TRIGGER_DEPTH));
154         }
155 
156         // SQLITE_LIMIT_WORKER_THREADS was added in SQLite 3.8.7.
157         if crate::version_number() >= 3_008_007 {
158             db.set_limit(Limit::SQLITE_LIMIT_WORKER_THREADS, 2);
159             assert_eq!(2, db.limit(Limit::SQLITE_LIMIT_WORKER_THREADS));
160         }
161         Ok(())
162     }
163 }
164