@@ -110,6 +110,11 @@ impl SqlDoc {
110110 pub fn tables ( & self ) -> & [ TableDoc ] {
111111 & self . tables
112112 }
113+ /// Method to move tables out of Structure if needed
114+ #[ must_use]
115+ pub fn into_tables ( self ) -> Vec < TableDoc > {
116+ self . tables
117+ }
113118 /// Getter method for returning the `Option<&[(PathBuf,SqlFileDoc)]>`
114119 #[ must_use]
115120 pub fn files ( & self ) -> Option < & [ ( PathBuf , SqlFileDoc ) ] > {
@@ -191,33 +196,131 @@ fn generate_docs_from_file<P: AsRef<Path>>(source: P) -> Result<(PathBuf, SqlFil
191196 Ok ( ( path, docs) )
192197}
193198
194-
195199#[ cfg( test) ]
196200mod tests {
197- use std:: { env, fs} ;
201+ use std:: { env, fs, path :: PathBuf } ;
198202
199- use crate :: { SqlDoc , docs:: { ColumnDoc , TableDoc } } ;
203+ use crate :: {
204+ SqlDoc ,
205+ docs:: { ColumnDoc , SqlFileDoc , TableDoc } ,
206+ error:: DocError ,
207+ } ;
200208
201-
202209 #[ test]
203- fn build_sql_doc_from_file ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
210+ fn build_sql_doc_from_file ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
204211 let base = env:: temp_dir ( ) . join ( "build_sql_doc_from_file" ) ;
205212 let _ = fs:: remove_dir_all ( & base) ;
206213 fs:: create_dir_all ( & base) ?;
207214 let file = base. join ( "test_file.sql" ) ;
208215 let sample = sample_sql ( ) ;
209- let ( mut contents, mut expected) : ( Vec < _ > , Vec < _ > ) = sample. into_iter ( ) . map ( | ( a , b ) | ( a , b ) ) . unzip ( ) ; ;
216+ let ( contents, expected) : ( Vec < _ > , Vec < _ > ) = sample. into_iter ( ) . unzip ( ) ;
210217 fs:: write ( & file, contents. join ( "" ) ) ?;
211- let sql_doc = SqlDoc :: from_path ( file) . build ( ) ?;
212- todo ! ( "combine the sample sqldocs Table Docs for testing" ) ;
213- assert_eq ! ( & sql_doc, expected) ;
218+ let sql_doc = SqlDoc :: from_path ( & file) . build ( ) ?;
219+ let doc = SqlDoc :: new ( expected. into_iter ( ) . flat_map ( SqlDoc :: into_tables) . collect ( ) , None ) ;
220+ assert_eq ! ( sql_doc, doc) ;
221+ let _ = fs:: remove_dir_all ( & base) ;
222+ Ok ( ( ) )
223+ }
224+ #[ test]
225+ fn build_sql_doc_from_dir ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
226+ let base = env:: temp_dir ( ) . join ( "build_sql_doc_from_dir" ) ;
227+ let _ = fs:: remove_dir_all ( & base) ;
228+ fs:: create_dir_all ( & base) ?;
229+ let sample = sample_sql ( ) ;
230+ let ( contents, expected) : ( Vec < _ > , Vec < _ > ) = sample. into_iter ( ) . unzip ( ) ;
231+ for ( idx, contents) in contents. iter ( ) . enumerate ( ) {
232+ let path = base. join ( format ! ( "test_file{idx}.sql" ) ) ;
233+ fs:: write ( & path, contents) ?;
234+ }
235+ let sql_doc = SqlDoc :: from_dir ( & base) . build ( ) ?;
236+ let mut actual: Vec < TableDoc > = sql_doc. into_tables ( ) ;
237+ dbg ! ( & actual) ;
238+ let mut expected: Vec < TableDoc > =
239+ expected. into_iter ( ) . flat_map ( SqlDoc :: into_tables) . collect ( ) ;
240+ assert_eq ! ( actual. len( ) , expected. len( ) ) ;
241+ sort_tables ( & mut actual) ;
242+ sort_tables ( & mut expected) ;
243+ assert_eq ! ( actual, expected) ;
244+ let _ = fs:: remove_dir_all ( & base) ;
214245 Ok ( ( ) )
215246 }
216247
217- fn sample_sql ( ) -> Vec < ( & ' static str , SqlDoc ) > {
218- vec ! [
219- (
220- r"
248+ #[ test]
249+ fn test_retrieve_table_and_schema ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
250+ let base = env:: temp_dir ( ) . join ( "build_sql_doc_with_schema" ) ;
251+ let _ = fs:: remove_dir_all ( & base) ;
252+ fs:: create_dir_all ( & base) ?;
253+ let file = base. join ( "test_file.sql" ) ;
254+ let sample = sample_sql ( ) ;
255+ let ( contents, expected) : ( Vec < _ > , Vec < _ > ) = sample. into_iter ( ) . unzip ( ) ;
256+ fs:: write ( & file, contents. join ( "" ) ) ?;
257+ let sql_doc = SqlDoc :: from_path ( & file) . build ( ) ?;
258+ let doc = SqlDoc :: new ( expected. into_iter ( ) . flat_map ( SqlDoc :: into_tables) . collect ( ) , None ) ;
259+ assert_eq ! ( sql_doc, doc) ;
260+ let table = "users" ;
261+ let actual_table = sql_doc. table ( table) ?;
262+ let expected_table = doc. table ( table) ?;
263+ assert_eq ! ( actual_table, expected_table) ;
264+ let schema = "analytics" ;
265+ let schema_table = "events" ;
266+ let actual_schema = sql_doc. table_with_schema ( schema, schema_table) ?;
267+ let expected_schema = doc. table_with_schema ( schema, schema_table) ?;
268+ assert_eq ! ( actual_schema, expected_schema) ;
269+ let _ = fs:: remove_dir_all ( & base) ;
270+ Ok ( ( ) )
271+ }
272+
273+ #[ test]
274+ fn test_table_err ( ) {
275+ let empty_set = SqlDoc :: new ( vec ! [ ] , None ) ;
276+ let empty_table_err = empty_set. table ( "name" ) ;
277+ assert ! ( empty_table_err. is_err( ) ) ;
278+ assert ! ( matches!(
279+ empty_table_err,
280+ Err ( DocError :: TableNotFound { name } ) if name == "name"
281+ ) ) ;
282+ let duplicate_set = SqlDoc :: new (
283+ vec ! [
284+ TableDoc :: new( None , "duplicate" . to_string( ) , None , vec![ ] ) ,
285+ TableDoc :: new( None , "duplicate" . to_string( ) , None , vec![ ] ) ,
286+ ] ,
287+ None ,
288+ ) ;
289+ let duplicate_tables_err = duplicate_set. table ( "duplicate" ) ;
290+ assert ! ( matches!( duplicate_tables_err, Err ( DocError :: DuplicateTablesFound { .. } ) ) ) ;
291+ }
292+
293+ #[ test]
294+ fn test_schema_err ( ) {
295+ let empty_set = SqlDoc :: new ( vec ! [ ] , None ) ;
296+ let empty_table_err = empty_set. table_with_schema ( "schema" , "name" ) ;
297+ assert ! ( empty_table_err. is_err( ) ) ;
298+ assert ! ( matches!(
299+ empty_table_err,
300+ Err ( DocError :: TableNotFound { name } ) if name == "name"
301+ ) ) ;
302+ let duplicate_set = SqlDoc :: new (
303+ vec ! [
304+ TableDoc :: new( Some ( "schema" . to_string( ) ) , "duplicate" . to_string( ) , None , vec![ ] ) ,
305+ TableDoc :: new( Some ( "schema" . to_string( ) ) , "duplicate" . to_string( ) , None , vec![ ] ) ,
306+ ] ,
307+ None ,
308+ ) ;
309+ let duplicate_tables_err = duplicate_set. table_with_schema ( "schema" , "duplicate" ) ;
310+ assert ! ( matches!( duplicate_tables_err, Err ( DocError :: DuplicateTablesFound { .. } ) ) ) ;
311+ }
312+ fn sort_tables ( tables : & mut [ TableDoc ] ) {
313+ tables. sort_by ( |a, b| {
314+ let a_key = ( a. schema ( ) . unwrap_or ( "" ) , a. name ( ) ) ;
315+ let b_key = ( b. schema ( ) . unwrap_or ( "" ) , b. name ( ) ) ;
316+ a_key. cmp ( & b_key)
317+ } ) ;
318+ }
319+
320+ fn sample_sql ( ) -> Vec < ( & ' static str , SqlDoc ) > {
321+ vec ! [
322+ (
323+ r"
221324 -- Users table
222325 CREATE TABLE users (
223326 -- id
@@ -226,66 +329,110 @@ fn sample_sql() -> Vec<(&'static str, SqlDoc)> {
226329 username TEXT NOT NULL
227330 );
228331 " ,
229- SqlDoc :: new(
230- vec![ TableDoc :: new(
332+ SqlDoc :: new(
333+ vec![ TableDoc :: new(
334+ None ,
335+ "users" . to_string( ) ,
336+ Some ( "Users table" . to_string( ) ) ,
337+ vec![
338+ ColumnDoc :: new( "id" . to_string( ) , Some ( "id" . to_string( ) ) ) ,
339+ ColumnDoc :: new( "username" . to_string( ) , Some ( "login name" . to_string( ) ) ) ,
340+ ] ,
341+ ) ] ,
231342 None ,
232- "users" . to_string( ) ,
233- Some ( "Users table" . to_string( ) ) ,
234- vec![
235- ColumnDoc :: new( "id" . to_string( ) , Some ( "id" . to_string( ) ) ) ,
236- ColumnDoc :: new( "username" . to_string( ) , Some ( "login name" . to_string( ) ) ) ,
237- ] ,
238- ) ] ,
239- None ,
343+ ) ,
240344 ) ,
241- ) ,
242-
243- (
244- r"
345+ (
346+ r"
245347 /* Posts table */
246348 CREATE TABLE posts (
247349 /* primary key */
248350 id INTEGER PRIMARY KEY,
249351 title TEXT NOT NULL
250352 );
251353 " ,
252- SqlDoc :: new(
253- vec![ TableDoc :: new(
354+ SqlDoc :: new(
355+ vec![ TableDoc :: new(
356+ None ,
357+ "posts" . to_string( ) ,
358+ Some ( "Posts table" . to_string( ) ) ,
359+ vec![
360+ ColumnDoc :: new( "id" . to_string( ) , Some ( "primary key" . to_string( ) ) ) ,
361+ ColumnDoc :: new( "title" . to_string( ) , None ) ,
362+ ] ,
363+ ) ] ,
254364 None ,
255- "posts" . to_string( ) ,
256- Some ( "Posts table" . to_string( ) ) ,
257- vec![
258- ColumnDoc :: new( "id" . to_string( ) , Some ( "primary key" . to_string( ) ) ) ,
259- ColumnDoc :: new( "title" . to_string( ) , None ) ,
260- ] ,
261- ) ] ,
262- None ,
365+ ) ,
263366 ) ,
264- ) ,
265-
266- (
267- r"
367+ (
368+ r"
268369 CREATE TABLE things (
269370 id INTEGER PRIMARY KEY,
270371 name TEXT,
271372 value INTEGER
272373 );
273374 " ,
274- SqlDoc :: new(
275- vec![ TableDoc :: new(
375+ SqlDoc :: new(
376+ vec![ TableDoc :: new(
377+ None ,
378+ "things" . to_string( ) ,
379+ None ,
380+ vec![
381+ ColumnDoc :: new( "id" . to_string( ) , None ) ,
382+ ColumnDoc :: new( "name" . to_string( ) , None ) ,
383+ ColumnDoc :: new( "value" . to_string( ) , None ) ,
384+ ] ,
385+ ) ] ,
276386 None ,
277- "things" . to_string( ) ,
387+ ) ,
388+ ) ,
389+ (
390+ r"
391+ -- Table with schema
392+ CREATE TABLE analytics.events (
393+ /* event id */
394+ id INTEGER PRIMARY KEY,
395+ /* event payload */
396+ payload TEXT
397+ );
398+ " ,
399+ SqlDoc :: new(
400+ vec![ TableDoc :: new(
401+ Some ( "analytics" . to_string( ) ) ,
402+ "events" . to_string( ) ,
403+ Some ( "Table with schema" . to_string( ) ) ,
404+ vec![
405+ ColumnDoc :: new( "id" . to_string( ) , Some ( "event id" . to_string( ) ) ) ,
406+ ColumnDoc :: new(
407+ "payload" . to_string( ) ,
408+ Some ( "event payload" . to_string( ) ) ,
409+ ) ,
410+ ] ,
411+ ) ] ,
278412 None ,
279- vec![
280- ColumnDoc :: new( "id" . to_string( ) , None ) ,
281- ColumnDoc :: new( "name" . to_string( ) , None ) ,
282- ColumnDoc :: new( "value" . to_string( ) , None ) ,
283- ] ,
284- ) ] ,
285- None ,
413+ ) ,
286414 ) ,
287- ) ,
288- ]
289- }
415+ ]
416+ }
417+
418+ #[ test]
419+ fn test_sql_doc_getters ( ) {
420+ let tables = vec ! [ TableDoc :: new( None , "name" . to_string( ) , None , vec![ ] ) ] ;
421+ let files = vec ! [ (
422+ PathBuf :: from( "file.sql" ) ,
423+ SqlFileDoc :: new( vec![ TableDoc :: new( None , "name" . to_string( ) , None , vec![ ] ) ] ) ,
424+ ) ] ;
425+ let sql_doc = SqlDoc :: new (
426+ vec ! [ TableDoc :: new( None , "name" . to_string( ) , None , vec![ ] ) ] ,
427+ Some ( vec ! [ (
428+ PathBuf :: from( "file.sql" ) ,
429+ SqlFileDoc :: new( vec![ TableDoc :: new( None , "name" . to_string( ) , None , vec![ ] ) ] ) ,
430+ ) ] ) ,
431+ ) ;
432+ assert_eq ! ( sql_doc. tables( ) . len( ) , 1 ) ;
433+ assert_eq ! ( sql_doc. tables( ) , tables) ;
290434
291- }
435+ assert_eq ! ( sql_doc. files( ) . iter( ) . len( ) , 1 ) ;
436+ assert_eq ! ( sql_doc. files( ) , Some ( files) . as_deref( ) ) ;
437+ }
438+ }
0 commit comments