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