1 //! Configure database connections
2 
3 use std::os::raw::c_int;
4 
5 use crate::error::check;
6 use crate::ffi;
7 use crate::{Connection, Result};
8 
9 /// Database Connection Configuration Options
10 /// See [Database Connection Configuration Options](https://sqlite.org/c3ref/c_dbconfig_enable_fkey.html) for details.
11 #[repr(i32)]
12 #[allow(non_snake_case, non_camel_case_types)]
13 #[non_exhaustive]
14 #[allow(clippy::upper_case_acronyms)]
15 pub enum DbConfig {
16     //SQLITE_DBCONFIG_MAINDBNAME = 1000, /* const char* */
17     //SQLITE_DBCONFIG_LOOKASIDE = 1001,  /* void* int int */
18     /// Enable or disable the enforcement of foreign key constraints.
19     SQLITE_DBCONFIG_ENABLE_FKEY = ffi::SQLITE_DBCONFIG_ENABLE_FKEY,
20     /// Enable or disable triggers.
21     SQLITE_DBCONFIG_ENABLE_TRIGGER = ffi::SQLITE_DBCONFIG_ENABLE_TRIGGER,
22     /// Enable or disable the fts3_tokenizer() function which is part of the
23     /// FTS3 full-text search engine extension.
24     SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER = ffi::SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, // 3.12.0
25     //SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION = 1005,
26     /// In WAL mode, enable or disable the checkpoint operation before closing
27     /// the connection.
28     SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE = 1006, // 3.16.2
29     /// Activates or deactivates the query planner stability guarantee (QPSG).
30     SQLITE_DBCONFIG_ENABLE_QPSG = 1007, // 3.20.0
31     /// Includes or excludes output for any operations performed by trigger
32     /// programs from the output of EXPLAIN QUERY PLAN commands.
33     SQLITE_DBCONFIG_TRIGGER_EQP = 1008, // 3.22.0
34     /// Activates or deactivates the "reset" flag for a database connection.
35     /// Run VACUUM with this flag set to reset the database.
36     SQLITE_DBCONFIG_RESET_DATABASE = 1009, // 3.24.0
37     /// Activates or deactivates the "defensive" flag for a database connection.
38     SQLITE_DBCONFIG_DEFENSIVE = 1010, // 3.26.0
39     /// Activates or deactivates the "writable_schema" flag.
40     #[cfg(feature = "modern_sqlite")]
41     SQLITE_DBCONFIG_WRITABLE_SCHEMA = 1011, // 3.28.0
42     /// Activates or deactivates the legacy behavior of the ALTER TABLE RENAME
43     /// command.
44     #[cfg(feature = "modern_sqlite")]
45     SQLITE_DBCONFIG_LEGACY_ALTER_TABLE = 1012, // 3.29
46     /// Activates or deactivates the legacy double-quoted string literal
47     /// misfeature for DML statements only.
48     #[cfg(feature = "modern_sqlite")]
49     SQLITE_DBCONFIG_DQS_DML = 1013, // 3.29.0
50     /// Activates or deactivates the legacy double-quoted string literal
51     /// misfeature for DDL statements.
52     #[cfg(feature = "modern_sqlite")]
53     SQLITE_DBCONFIG_DQS_DDL = 1014, // 3.29.0
54     /// Enable or disable views.
55     #[cfg(feature = "modern_sqlite")]
56     SQLITE_DBCONFIG_ENABLE_VIEW = 1015, // 3.30.0
57     /// Activates or deactivates the legacy file format flag.
58     #[cfg(feature = "modern_sqlite")]
59     SQLITE_DBCONFIG_LEGACY_FILE_FORMAT = 1016, // 3.31.0
60     /// Tells SQLite to assume that database schemas (the contents of the
61     /// sqlite_master tables) are untainted by malicious content.
62     #[cfg(feature = "modern_sqlite")]
63     SQLITE_DBCONFIG_TRUSTED_SCHEMA = 1017, // 3.31.0
64 }
65 
66 impl Connection {
67     /// Returns the current value of a `config`.
68     ///
69     /// - `SQLITE_DBCONFIG_ENABLE_FKEY`: return `false` or `true` to indicate
70     ///   whether FK enforcement is off or on
71     /// - `SQLITE_DBCONFIG_ENABLE_TRIGGER`: return `false` or `true` to indicate
72     ///   whether triggers are disabled or enabled
73     /// - `SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER`: return `false` or `true` to
74     ///   indicate whether `fts3_tokenizer` are disabled or enabled
75     /// - `SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE`: return `false` to indicate
76     ///   checkpoints-on-close are not disabled or `true` if they are
77     /// - `SQLITE_DBCONFIG_ENABLE_QPSG`: return `false` or `true` to indicate
78     ///   whether the QPSG is disabled or enabled
79     /// - `SQLITE_DBCONFIG_TRIGGER_EQP`: return `false` to indicate
80     ///   output-for-trigger are not disabled or `true` if it is
81     #[inline]
db_config(&self, config: DbConfig) -> Result<bool>82     pub fn db_config(&self, config: DbConfig) -> Result<bool> {
83         let c = self.db.borrow();
84         unsafe {
85             let mut val = 0;
86             check(ffi::sqlite3_db_config(
87                 c.db(),
88                 config as c_int,
89                 -1,
90                 &mut val,
91             ))?;
92             Ok(val != 0)
93         }
94     }
95 
96     /// Make configuration changes to a database connection
97     ///
98     /// - `SQLITE_DBCONFIG_ENABLE_FKEY`: `false` to disable FK enforcement,
99     ///   `true` to enable FK enforcement
100     /// - `SQLITE_DBCONFIG_ENABLE_TRIGGER`: `false` to disable triggers, `true`
101     ///   to enable triggers
102     /// - `SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER`: `false` to disable
103     ///   `fts3_tokenizer()`, `true` to enable `fts3_tokenizer()`
104     /// - `SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE`: `false` (the default) to enable
105     ///   checkpoints-on-close, `true` to disable them
106     /// - `SQLITE_DBCONFIG_ENABLE_QPSG`: `false` to disable the QPSG, `true` to
107     ///   enable QPSG
108     /// - `SQLITE_DBCONFIG_TRIGGER_EQP`: `false` to disable output for trigger
109     ///   programs, `true` to enable it
110     #[inline]
set_db_config(&self, config: DbConfig, new_val: bool) -> Result<bool>111     pub fn set_db_config(&self, config: DbConfig, new_val: bool) -> Result<bool> {
112         let c = self.db.borrow_mut();
113         unsafe {
114             let mut val = 0;
115             check(ffi::sqlite3_db_config(
116                 c.db(),
117                 config as c_int,
118                 new_val as c_int,
119                 &mut val,
120             ))?;
121             Ok(val != 0)
122         }
123     }
124 }
125 
126 #[cfg(test)]
127 mod test {
128     use super::DbConfig;
129     use crate::{Connection, Result};
130 
131     #[test]
test_db_config() -> Result<()>132     fn test_db_config() -> Result<()> {
133         let db = Connection::open_in_memory()?;
134 
135         let opposite = !db.db_config(DbConfig::SQLITE_DBCONFIG_ENABLE_FKEY)?;
136         assert_eq!(
137             db.set_db_config(DbConfig::SQLITE_DBCONFIG_ENABLE_FKEY, opposite),
138             Ok(opposite)
139         );
140         assert_eq!(
141             db.db_config(DbConfig::SQLITE_DBCONFIG_ENABLE_FKEY),
142             Ok(opposite)
143         );
144 
145         let opposite = !db.db_config(DbConfig::SQLITE_DBCONFIG_ENABLE_TRIGGER)?;
146         assert_eq!(
147             db.set_db_config(DbConfig::SQLITE_DBCONFIG_ENABLE_TRIGGER, opposite),
148             Ok(opposite)
149         );
150         assert_eq!(
151             db.db_config(DbConfig::SQLITE_DBCONFIG_ENABLE_TRIGGER),
152             Ok(opposite)
153         );
154         Ok(())
155     }
156 }
157