@@ -54,9 +54,11 @@ enum SqlFileDocSource<'a> {
5454impl SqlDoc {
5555 /// Method for creating a new [`SqlDoc`]
5656 #[ must_use]
57- pub const fn new ( tables : Vec < TableDoc > ) -> Self {
57+ pub fn new ( mut tables : Vec < TableDoc > ) -> Self {
58+ tables. sort_by ( |a, b| a. name ( ) . cmp ( b. name ( ) ) ) ;
5859 Self { tables }
5960 }
61+
6062 /// Method for generating builder from a directory.
6163 pub fn from_dir < P : AsRef < Path > > ( root : & P ) -> SqlDocBuilder < ' _ > {
6264 SqlDocBuilder {
@@ -102,20 +104,11 @@ impl SqlDoc {
102104 ///
103105 /// # Errors
104106 /// - Will return [`DocError::TableNotFound`] if the expected table is not found
105- /// - Will return [`DocError::DuplicateTablesFound`] if more than one table is found
106- pub fn table ( & self , table : & str ) -> Result < & TableDoc , DocError > {
107- let matches = self
108- . tables
109- . iter ( )
110- . filter ( |table_doc| table_doc. name ( ) == table)
111- . collect :: < Vec < & TableDoc > > ( ) ;
112- match matches. as_slice ( ) {
113- [ ] => Err ( DocError :: TableNotFound { name : table. to_owned ( ) } ) ,
114- [ only] => Ok ( * only) ,
115- _ => Err ( DocError :: DuplicateTablesFound {
116- tables : matches. into_iter ( ) . cloned ( ) . collect ( ) ,
117- } ) ,
118- }
107+ pub fn table ( & self , name : & str ) -> Result < & TableDoc , DocError > {
108+ self . tables ( ) . binary_search_by ( |t| t. name ( ) . cmp ( name) ) . map_or_else (
109+ |_| Err ( DocError :: TableNotFound { name : name. to_owned ( ) } ) ,
110+ |id| Ok ( & self . tables ( ) [ id] ) ,
111+ )
119112 }
120113
121114 /// Method for finding a specific [`TableDoc`] from `schema` and table `name`
@@ -222,7 +215,7 @@ impl SqlDocBuilder<'_> {
222215 for sql_doc in docs {
223216 tables. extend ( sql_doc) ;
224217 }
225- let mut sql_doc = SqlDoc { tables } ;
218+ let mut sql_doc = SqlDoc :: new ( tables) ;
226219 match self . multiline_flat {
227220 MultiFlatten :: FlattenWithNone => {
228221 sql_doc = flatten_docs ( sql_doc, None ) ;
@@ -334,6 +327,11 @@ mod tests {
334327 stamp_table_paths ( & mut expected_tables, & file) ;
335328 let expected_doc = SqlDoc :: new ( expected_tables) ;
336329 assert_eq ! ( sql_doc, expected_doc) ;
330+ let names: Vec < & str > =
331+ sql_doc. tables ( ) . iter ( ) . map ( super :: super :: docs:: TableDoc :: name) . collect ( ) ;
332+ let mut sorted = names. clone ( ) ;
333+ sorted. sort_unstable ( ) ;
334+ assert_eq ! ( names, sorted, "tables should be in alphabetical order" ) ;
337335 let _ = fs:: remove_dir_all ( & base) ;
338336 Ok ( ( ) )
339337 }
@@ -396,12 +394,6 @@ mod tests {
396394 empty_table_err,
397395 Err ( DocError :: TableNotFound { name } ) if name == "name"
398396 ) ) ;
399- let duplicate_set = SqlDoc :: new ( vec ! [
400- TableDoc :: new( None , "duplicate" . to_owned( ) , None , vec![ ] , None ) ,
401- TableDoc :: new( None , "duplicate" . to_owned( ) , None , vec![ ] , None ) ,
402- ] ) ;
403- let duplicate_tables_err = duplicate_set. table ( "duplicate" ) ;
404- assert ! ( matches!( duplicate_tables_err, Err ( DocError :: DuplicateTablesFound { .. } ) ) ) ;
405397 }
406398
407399 #[ test]
@@ -720,7 +712,7 @@ mod tests {
720712 }
721713
722714 #[ test]
723- fn test_fromstr_parse_sql_doc ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
715+ fn test_from_str_parse_sql_doc ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
724716 let doc: SqlDoc = "CREATE TABLE t(id INTEGER);" . parse ( ) ?;
725717 assert_eq ! ( doc. tables( ) . len( ) , 1 ) ;
726718 Ok ( ( ) )
@@ -764,4 +756,17 @@ mod tests {
764756 let _ = fs:: remove_dir_all ( & base) ;
765757 Ok ( ( ) )
766758 }
759+
760+ #[ test]
761+ fn test_tables_binary_searchable_by_name ( ) {
762+ let sample = sample_sql ( ) ;
763+ let tables: Vec < TableDoc > =
764+ sample. into_iter ( ) . flat_map ( |( _, doc) | doc. into_tables ( ) ) . collect ( ) ;
765+ let sql_doc = SqlDoc :: new ( tables) ;
766+ let id = sql_doc
767+ . tables ( )
768+ . binary_search_by ( |t| t. name ( ) . cmp ( "users" ) )
769+ . unwrap_or_else ( |_| panic ! ( "expected to find table `users` via binary search" ) ) ;
770+ assert_eq ! ( sql_doc. tables( ) [ id] . name( ) , "users" ) ;
771+ }
767772}
0 commit comments