11//! Public entry point for building [`SqlDoc`] from a directory, file, or string.
22
3- use std:: { path:: { Path , PathBuf } , str:: FromStr } ;
3+ use std:: {
4+ path:: { Path , PathBuf } ,
5+ str:: FromStr ,
6+ } ;
47
58use crate :: {
69 ast:: ParsedSqlFile ,
@@ -44,6 +47,7 @@ pub enum MultiFlatten {
4447enum SqlFileDocSource < ' a > {
4548 Dir ( PathBuf ) ,
4649 File ( PathBuf ) ,
50+ Files ( Vec < PathBuf > ) ,
4751 FromString ( & ' a str ) ,
4852}
4953
@@ -54,7 +58,7 @@ impl SqlDoc {
5458 Self { tables }
5559 }
5660 /// Method for generating builder from a directory.
57- pub fn from_dir < P : AsRef < Path > + ? Sized > ( root : & P ) -> SqlDocBuilder < ' _ > {
61+ pub fn from_dir < P : AsRef < Path > > ( root : & P ) -> SqlDocBuilder < ' _ > {
5862 SqlDocBuilder {
5963 source : SqlFileDocSource :: Dir ( root. as_ref ( ) . to_path_buf ( ) ) ,
6064 deny : Vec :: new ( ) ,
@@ -70,6 +74,17 @@ impl SqlDoc {
7074 }
7175 }
7276
77+ /// Method for generating builder from a [`[Path]`]
78+ pub fn from_paths < P : AsRef < Path > > ( paths : & [ P ] ) -> SqlDocBuilder < ' _ > {
79+ SqlDocBuilder {
80+ source : SqlFileDocSource :: Files (
81+ paths. iter ( ) . map ( |p| p. as_ref ( ) . to_path_buf ( ) ) . collect ( ) ,
82+ ) ,
83+ deny : Vec :: new ( ) ,
84+ multiline_flat : MultiFlatten :: NoFlat ,
85+ }
86+ }
87+
7388 /// Creates a builder from SQL text (no filesystem path is associated) from a [`str`]
7489 #[ must_use]
7590 pub const fn builder_from_str ( content : & str ) -> SqlDocBuilder < ' _ > {
@@ -148,7 +163,7 @@ impl FromStr for SqlDoc {
148163 type Err = DocError ;
149164
150165 fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
151- SqlDoc :: builder_from_str ( s) . build ( )
166+ Self :: builder_from_str ( s) . build ( )
152167 }
153168}
154169
@@ -200,6 +215,7 @@ impl SqlDocBuilder<'_> {
200215 let sql_docs = generate_docs_str ( content) ?;
201216 vec ! [ sql_docs]
202217 }
218+ SqlFileDocSource :: Files ( files) => generate_docs_from_files ( files) ?,
203219 } ;
204220 let num_of_tables = docs. iter ( ) . map ( super :: docs:: SqlFileDoc :: number_of_tables) . sum ( ) ;
205221 let mut tables = Vec :: with_capacity ( num_of_tables) ;
@@ -263,6 +279,15 @@ fn generate_docs_from_dir<P: AsRef<Path>, S: AsRef<str>>(
263279 Ok ( sql_docs)
264280}
265281
282+ fn generate_docs_from_files ( files : & [ PathBuf ] ) -> Result < Vec < SqlFileDoc > , DocError > {
283+ let mut sql_docs = Vec :: new ( ) ;
284+ for file in files {
285+ let docs = generate_docs_from_file ( file) ?;
286+ sql_docs. push ( docs) ;
287+ }
288+ Ok ( sql_docs)
289+ }
290+
266291fn generate_docs_from_file < P : AsRef < Path > > ( source : P ) -> Result < SqlFileDoc , DocError > {
267292 let file = SqlFile :: new ( source. as_ref ( ) ) ?;
268293 let parsed_file = ParsedSqlFile :: parse ( file) ?;
@@ -695,10 +720,48 @@ mod tests {
695720 }
696721
697722 #[ test]
698- fn test_fromstr_parse_sql_doc ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
699- let doc: SqlDoc = "CREATE TABLE t(id INTEGER);" . parse ( ) ?;
700- assert_eq ! ( doc. tables( ) . len( ) , 1 ) ;
701- Ok ( ( ) )
702- }
723+ fn test_fromstr_parse_sql_doc ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
724+ let doc: SqlDoc = "CREATE TABLE t(id INTEGER);" . parse ( ) ?;
725+ assert_eq ! ( doc. tables( ) . len( ) , 1 ) ;
726+ Ok ( ( ) )
727+ }
728+
729+ #[ test]
730+ fn test_build_sql_doc_from_paths ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
731+ let base = env:: temp_dir ( ) . join ( "build_sql_doc_from_paths" ) ;
732+ let _ = fs:: remove_dir_all ( & base) ;
733+ fs:: create_dir_all ( & base) ?;
734+ let sample = sample_sql ( ) ;
735+ let ( sql1, doc1) = & sample[ 0 ] ;
736+ let ( sql2, doc2) = & sample[ 1 ] ;
737+
738+ let file1 = base. join ( "one.sql" ) ;
739+ let file2 = base. join ( "two.sql" ) ;
740+ fs:: write ( & file1, sql1) ?;
741+ fs:: write ( & file2, sql2) ?;
742+
743+ let paths = vec ! [ file1. clone( ) , file2. clone( ) ] ;
744+ let sql_doc = SqlDoc :: from_paths ( & paths) . build ( ) ?;
745+
746+ let mut expected_tables: Vec < TableDoc > = Vec :: new ( ) ;
703747
748+ let mut t1 = doc1. clone ( ) . into_tables ( ) ;
749+ stamp_table_paths ( & mut t1, & file1) ;
750+ expected_tables. extend ( t1) ;
751+
752+ let mut t2 = doc2. clone ( ) . into_tables ( ) ;
753+ stamp_table_paths ( & mut t2, & file2) ;
754+ expected_tables. extend ( t2) ;
755+
756+ let mut actual_tables = sql_doc. into_tables ( ) ;
757+ assert_eq ! ( actual_tables. len( ) , expected_tables. len( ) ) ;
758+
759+ sort_tables ( & mut actual_tables) ;
760+ sort_tables ( & mut expected_tables) ;
761+
762+ assert_eq ! ( actual_tables, expected_tables) ;
763+
764+ let _ = fs:: remove_dir_all ( & base) ;
765+ Ok ( ( ) )
766+ }
704767}
0 commit comments