Skip to content

Commit c5784b8

Browse files
authored
Merge pull request #2610 from fermyon/allow-migrations-in-non-default
Allow sqlite migrations for non-default databases.
2 parents d6d9cbc + 096904e commit c5784b8

File tree

1 file changed

+45
-9
lines changed

1 file changed

+45
-9
lines changed

crates/trigger/src/runtime_config/sqlite.rs

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,24 +49,27 @@ async fn execute_statements(
4949
if statements.is_empty() {
5050
return Ok(());
5151
}
52-
let Some(default) = databases.get("default") else {
53-
debug_assert!(
54-
false,
55-
"the 'default' sqlite database should always be available but for some reason was not"
56-
);
57-
return Ok(());
58-
};
5952

6053
for m in statements {
61-
if let Some(file) = m.strip_prefix('@') {
54+
if let Some(config) = m.strip_prefix('@') {
55+
let (file, database) = parse_file_and_label(config)?;
56+
let database = databases.get(database).with_context(|| {
57+
format!(
58+
"based on the '@{config}' a registered database named '{database}' was expected but not found. The registered databases are '{:?}'", databases.keys()
59+
)
60+
})?;
6261
let sql = std::fs::read_to_string(file).with_context(|| {
6362
format!("could not read file '{file}' containing sql statements")
6463
})?;
65-
default
64+
database
6665
.execute_batch(&sql)
6766
.await
6867
.with_context(|| format!("failed to execute sql from file '{file}'"))?;
6968
} else {
69+
let Some(default) = databases.get("default") else {
70+
debug_assert!(false, "the 'default' sqlite database should always be available but for some reason was not");
71+
return Ok(());
72+
};
7073
default
7174
.query(m, Vec::new())
7275
.await
@@ -76,6 +79,19 @@ async fn execute_statements(
7679
Ok(())
7780
}
7881

82+
/// Parses a @{file:label} sqlite statement
83+
fn parse_file_and_label(config: &str) -> anyhow::Result<(&str, &str)> {
84+
let config = config.trim();
85+
let (file, label) = match config.split_once(':') {
86+
Some((_, label)) if label.trim().is_empty() => {
87+
anyhow::bail!("database label is empty in the '@{config}' sqlite statement")
88+
}
89+
Some((file, label)) => (file.trim(), label.trim()),
90+
None => (config, "default"),
91+
};
92+
Ok((file, label))
93+
}
94+
7995
// Holds deserialized options from a `[sqlite_database.<name>]` runtime config section.
8096
#[derive(Clone, Debug, serde::Deserialize)]
8197
#[serde(rename_all = "snake_case", tag = "type")]
@@ -202,3 +218,23 @@ impl TriggerHooks for SqlitePersistenceMessageHook {
202218
Ok(())
203219
}
204220
}
221+
222+
#[cfg(test)]
223+
mod tests {
224+
use super::*;
225+
226+
#[test]
227+
fn can_parse_file_and_label() {
228+
let config = "file:label";
229+
let result = parse_file_and_label(config).unwrap();
230+
assert_eq!(result, ("file", "label"));
231+
232+
let config = "file:";
233+
let result = parse_file_and_label(config);
234+
assert!(result.is_err());
235+
236+
let config = "file";
237+
let result = parse_file_and_label(config).unwrap();
238+
assert_eq!(result, ("file", "default"));
239+
}
240+
}

0 commit comments

Comments
 (0)