MCPcopy Create free account
hub / github.com/chatmail/core / import

Method import

src/sql.rs:126–175  ·  view source on GitHub ↗

Imports the database from a separate file with the given passphrase.

(&self, path: &Path, passphrase: String)

Source from the content-addressed store, hash-verified

124
125 /// Imports the database from a separate file with the given passphrase.
126 pub(crate) async fn import(&self, path: &Path, passphrase: String) -> Result<()> {
127 let path_str = path
128 .to_str()
129 .with_context(|| format!("path {path:?} is not valid unicode"))?
130 .to_string();
131
132 // Keep `config_cache` locked all the time the db is imported so that nobody can use invalid
133 // values from there. And clear it immediately so as not to forget in case of errors.
134 let mut config_cache = self.config_cache.write().await;
135 config_cache.clear();
136
137 let query_only = false;
138 self.call(query_only, move |conn| {
139 // Check that backup passphrase is correct before resetting our database.
140 conn.execute("ATTACH DATABASE ? AS backup KEY ?", (path_str, passphrase))
141 .context("failed to attach backup database")?;
142 let res = conn
143 .query_row("SELECT count(*) FROM sqlite_master", [], |_row| Ok(()))
144 .context("backup passphrase is not correct");
145
146 // Reset the database without reopening it. We don't want to reopen the database because we
147 // don't have main database passphrase at this point.
148 // See <https://sqlite.org/c3ref/c_dbconfig_enable_fkey.html> for documentation.
149 // Without resetting import may fail due to existing tables.
150 res.and_then(|_| {
151 conn.set_db_config(DbConfig::SQLITE_DBCONFIG_RESET_DATABASE, true)
152 .context("failed to set SQLITE_DBCONFIG_RESET_DATABASE")
153 })
154 .and_then(|_| {
155 conn.execute("VACUUM", [])
156 .context("failed to vacuum the database")
157 })
158 .and(
159 conn.set_db_config(DbConfig::SQLITE_DBCONFIG_RESET_DATABASE, false)
160 .context("failed to unset SQLITE_DBCONFIG_RESET_DATABASE"),
161 )
162 .and_then(|_| {
163 conn.query_row("SELECT sqlcipher_export('main', 'backup')", [], |_row| {
164 Ok(())
165 })
166 .context("failed to import from attached backup database")
167 })
168 .and(
169 conn.execute("DETACH DATABASE backup", [])
170 .context("failed to detach backup database"),
171 )?;
172 Ok(())
173 })
174 .await
175 }
176
177 const N_DB_CONNECTIONS: usize = 3;
178

Callers 1

Calls 3

callMethod · 0.80
executeMethod · 0.80
query_rowMethod · 0.80

Tested by

no test coverage detected