@@ -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