@@ -126,7 +126,7 @@ impl fmt::Display for TableDoc {
126126
127127 writeln ! ( f, "Table Column Docs: " ) ?;
128128 for col in self . columns ( ) {
129- writeln ! ( f, " {col}" ) ?;
129+ write ! ( f, " {col}" ) ?;
130130 }
131131 Ok ( ( ) )
132132 }
@@ -244,7 +244,17 @@ fn schema_and_table(name: &ObjectName) -> Result<(Option<String>, String), DocEr
244244
245245#[ cfg( test) ]
246246mod tests {
247- use crate :: docs:: { ColumnDoc , SqlFileDoc , TableDoc } ;
247+ use core:: fmt;
248+
249+ use sqlparser:: {
250+ ast:: { Ident , ObjectName , ObjectNamePart , ObjectNamePartFunction } ,
251+ tokenizer:: Span ,
252+ } ;
253+
254+ use crate :: {
255+ docs:: { ColumnDoc , SqlFileDoc , TableDoc , schema_and_table} ,
256+ error:: DocError ,
257+ } ;
248258
249259 #[ test]
250260 fn test_sql_docs_struct ( ) {
@@ -425,7 +435,153 @@ mod tests {
425435 #[ test]
426436 fn test_doc ( ) {
427437 let col_doc = ColumnDoc :: new ( "test" . to_string ( ) , Some ( "comment" . to_string ( ) ) ) ;
438+ assert_eq ! ( & col_doc. to_string( ) , & "Column Name: test\n Column Doc: comment\n " . to_string( ) ) ;
439+ let col_doc_no_doc = ColumnDoc :: new ( "test" . to_string ( ) , None ) ;
440+ assert_eq ! (
441+ & col_doc_no_doc. to_string( ) ,
442+ & "Column Name: test\n No Column Doc Found\n " . to_string( )
443+ ) ;
428444 assert_eq ! ( col_doc. doc( ) , Some ( "comment" ) ) ;
429445 assert_eq ! ( col_doc. name( ) , "test" ) ;
446+ assert_eq ! ( col_doc_no_doc. doc( ) , None ) ;
447+ assert_eq ! ( col_doc_no_doc. name( ) , "test" ) ;
448+ let table_doc = TableDoc :: new (
449+ Some ( "schema" . to_string ( ) ) ,
450+ "table" . to_string ( ) ,
451+ Some ( "table doc" . to_string ( ) ) ,
452+ vec ! [ col_doc] ,
453+ ) ;
454+ let table_doc_no_doc = TableDoc :: new ( None , "table" . to_string ( ) , None , vec ! [ col_doc_no_doc] ) ;
455+ assert_eq ! ( table_doc. name( ) , "table" ) ;
456+ assert_eq ! ( table_doc. schema( ) , Some ( "schema" ) ) ;
457+ assert_eq ! (
458+ table_doc. to_string( ) ,
459+ "Table Schema: schema\n Table Name: table\n Table Doc: table doc\n Table Column Docs: \n Column Name: test\n Column Doc: comment\n "
460+ ) ;
461+ assert_eq ! ( table_doc_no_doc. schema( ) , None ) ;
462+ assert_eq ! ( table_doc_no_doc. name( ) , "table" ) ;
463+ assert_eq ! (
464+ table_doc_no_doc. to_string( ) ,
465+ "No Table Schema\n Table Name: table\n No Table Doc\n Table Column Docs: \n Column Name: test\n No Column Doc Found\n "
466+ ) ;
467+ }
468+
469+ fn ident ( v : & str ) -> Ident {
470+ Ident { value : v. to_string ( ) , quote_style : None , span : Span :: empty ( ) }
471+ }
472+
473+ fn func_part ( name : & str ) -> ObjectNamePart {
474+ ObjectNamePart :: Function ( ObjectNamePartFunction { name : ident ( name) , args : vec ! [ ] } )
475+ }
476+
477+ #[ test]
478+ fn schema_and_table_errors_when_no_identifier_parts ( ) {
479+ let name = ObjectName ( vec ! [ func_part( "now" ) ] ) ;
480+
481+ let err = match schema_and_table ( & name) {
482+ Ok ( v) => panic ! ( "expected Err(DocError::InvalidObjectName), got Ok({v:?})" ) ,
483+ Err ( e) => e,
484+ } ;
485+
486+ match err {
487+ DocError :: InvalidObjectName { message, .. } => {
488+ assert_eq ! ( message, "ObjectName had no identifier parts" ) ;
489+ }
490+ other => panic ! ( "unexpected error: {other:?}" ) ,
491+ }
492+ }
493+
494+ #[ test]
495+ fn schema_and_table_single_identifier ( ) {
496+ let name = ObjectName ( vec ! [ ObjectNamePart :: Identifier ( ident( "users" ) ) ] ) ;
497+
498+ let ( schema, table) = match schema_and_table ( & name) {
499+ Ok ( v) => v,
500+ Err ( e) => panic ! ( "unexpected error: {e:?}" ) ,
501+ } ;
502+
503+ assert_eq ! ( schema, None ) ;
504+ assert_eq ! ( table, "users" ) ;
505+ }
506+
507+ #[ test]
508+ fn schema_and_table_schema_and_table_with_function_ignored ( )
509+ -> Result < ( ) , Box < dyn std:: error:: Error > > {
510+ let name = ObjectName ( vec ! [
511+ ObjectNamePart :: Identifier ( ident( "catalog" ) ) ,
512+ ObjectNamePart :: Identifier ( ident( "public" ) ) ,
513+ func_part( "some_func" ) ,
514+ ObjectNamePart :: Identifier ( ident( "orders" ) ) ,
515+ ] ) ;
516+
517+ let ( schema, table) = schema_and_table ( & name) ?;
518+ assert_eq ! ( schema, Some ( "public" . to_string( ) ) ) ;
519+ assert_eq ! ( table, "orders" ) ;
520+ Ok ( ( ) )
521+ }
522+
523+ struct FailOnNthWrite {
524+ fail_at : usize ,
525+ writes : usize ,
526+ sink : String ,
527+ }
528+
529+ impl FailOnNthWrite {
530+ fn new ( fail_at : usize ) -> Self {
531+ Self { fail_at, writes : 0 , sink : String :: new ( ) }
532+ }
533+ }
534+
535+ impl fmt:: Write for FailOnNthWrite {
536+ fn write_str ( & mut self , s : & str ) -> fmt:: Result {
537+ self . writes += 1 ;
538+ if self . writes == self . fail_at {
539+ return Err ( fmt:: Error ) ;
540+ }
541+ self . sink . push_str ( s) ;
542+ Ok ( ( ) )
543+ }
544+ }
545+
546+ fn run_fail_at < T : fmt:: Display > ( v : & T , fail_at : usize ) -> Result < ( ) , fmt:: Error > {
547+ let mut w = FailOnNthWrite :: new ( fail_at) ;
548+ fmt:: write ( & mut w, format_args ! ( "{v}" ) )
549+ }
550+
551+ fn count_writes < T : fmt:: Display > ( v : & T ) -> usize {
552+ let mut w = FailOnNthWrite { fail_at : usize:: MAX , writes : 0 , sink : String :: new ( ) } ;
553+ // We don't care if this errors (it shouldn't with fail_at=MAX), we only want the write count.
554+ let _ = fmt:: write ( & mut w, format_args ! ( "{v}" ) ) ;
555+ w. writes
556+ }
557+
558+ #[ test]
559+ fn display_propagates_every_question_mark_path_for_column_and_table ( ) {
560+ let col_with_doc = ColumnDoc :: new ( "col_a" . into ( ) , Some ( "doc" . into ( ) ) ) ;
561+ let col_without_doc = ColumnDoc :: new ( "col_b" . into ( ) , None ) ;
562+
563+ let table = TableDoc :: new (
564+ Some ( "public" . into ( ) ) ,
565+ "users" . into ( ) ,
566+ Some ( "table doc" . into ( ) ) ,
567+ vec ! [ col_with_doc. clone( ) , col_without_doc] ,
568+ ) ;
569+
570+ let col_writes = count_writes ( & col_with_doc) ;
571+ let table_writes = count_writes ( & table) ;
572+
573+ for i in 1 ..=col_writes {
574+ assert ! (
575+ run_fail_at( & col_with_doc, i) . is_err( ) ,
576+ "ColumnDoc should error when failing at write #{i} (total writes {col_writes})"
577+ ) ;
578+ }
579+
580+ for i in 1 ..=table_writes {
581+ assert ! (
582+ run_fail_at( & table, i) . is_err( ) ,
583+ "TableDoc should error when failing at write #{i} (total writes {table_writes})"
584+ ) ;
585+ }
430586 }
431587}
0 commit comments