@@ -715,30 +715,42 @@ fn should_remove_item_statement(
715715fn insert_definition_at_block_end ( block : & str , definition : & str ) -> String {
716716 let trimmed_len = block. trim_end ( ) . len ( ) ;
717717 let ( body, trailing) = block. split_at ( trimmed_len) ;
718- let trimmed_definition = definition. trim ( ) ;
718+ let terminated_definition = terminate_definition ( definition) ;
719+ if terminated_definition. is_empty ( ) {
720+ return block. to_string ( ) ;
721+ }
719722
720723 if body. is_empty ( ) {
721- return format ! ( "{trimmed_definition }{trailing}" ) ;
724+ return format ! ( "{terminated_definition }{trailing}" ) ;
722725 }
723726
724- format ! ( "{body}\n \n {trimmed_definition }{trailing}" )
727+ format ! ( "{body}\n \n {terminated_definition }{trailing}" )
725728}
726729
727730fn append_definition_to_content ( content : & str , definition : & str ) -> String {
728- let trimmed_definition = definition . trim ( ) ;
729- if trimmed_definition . is_empty ( ) {
731+ let terminated_definition = terminate_definition ( definition ) ;
732+ if terminated_definition . is_empty ( ) {
730733 return content. trim_end ( ) . to_string ( ) ;
731734 }
732735
733736 let mut result = content. trim_end ( ) . to_string ( ) ;
734737 if !result. is_empty ( ) {
735738 result. push_str ( "\n \n " ) ;
736739 }
737- result. push_str ( trimmed_definition ) ;
740+ result. push_str ( & terminated_definition ) ;
738741 result. push ( '\n' ) ;
739742 result
740743}
741744
745+ fn terminate_definition ( definition : & str ) -> String {
746+ let trimmed_definition = definition. trim ( ) ;
747+ if trimmed_definition. is_empty ( ) || trimmed_definition. ends_with ( ';' ) {
748+ trimmed_definition. to_string ( )
749+ } else {
750+ format ! ( "{trimmed_definition};" )
751+ }
752+ }
753+
742754fn read_definitions_file ( path : & Path ) -> io:: Result < String > {
743755 match fs:: read_to_string ( path) {
744756 Ok ( content) => Ok ( content) ,
@@ -2008,6 +2020,60 @@ models:
20082020 remove_definitions_file ( & db_path) ;
20092021 }
20102022
2023+ #[ test]
2024+ fn test_semicolonless_simple_as_definition_is_terminated_before_append ( ) {
2025+ let _guard = test_lock ( ) ;
2026+ sidemantic_clear ( ) ;
2027+
2028+ let db_path = unique_db_path ( "semicolonless_simple_as_append" ) ;
2029+ let db_path = CString :: new ( db_path. to_string_lossy ( ) . to_string ( ) ) . unwrap ( ) ;
2030+ remove_definitions_file ( & db_path) ;
2031+ let definitions_path = get_definitions_path ( db_path. as_ptr ( ) ) . unwrap ( ) ;
2032+
2033+ let orders =
2034+ CString :: new ( "MODEL (name orders, table orders, primary_key order_id)" ) . unwrap ( ) ;
2035+ assert_success ( sidemantic_define ( orders. as_ptr ( ) , db_path. as_ptr ( ) , false ) ) ;
2036+
2037+ let metric = CString :: new ( "METRIC revenue AS SUM(amount)" ) . unwrap ( ) ;
2038+ assert_success ( sidemantic_add_definition (
2039+ metric. as_ptr ( ) ,
2040+ db_path. as_ptr ( ) ,
2041+ false ,
2042+ ) ) ;
2043+
2044+ let customers =
2045+ CString :: new ( "MODEL (name customers, table customers, primary_key customer_id)" )
2046+ . unwrap ( ) ;
2047+ assert_success ( sidemantic_define (
2048+ customers. as_ptr ( ) ,
2049+ db_path. as_ptr ( ) ,
2050+ false ,
2051+ ) ) ;
2052+
2053+ let content = fs:: read_to_string ( & definitions_path) . unwrap ( ) ;
2054+ assert ! (
2055+ content. contains( "METRIC revenue AS SUM(amount);\n \n MODEL (name customers" ) ,
2056+ "{content}"
2057+ ) ;
2058+
2059+ sidemantic_clear ( ) ;
2060+ assert_success ( sidemantic_autoload ( db_path. as_ptr ( ) ) ) ;
2061+
2062+ let customers_name = CString :: new ( "customers" ) . unwrap ( ) ;
2063+ assert ! ( sidemantic_is_model( customers_name. as_ptr( ) ) ) ;
2064+
2065+ let rewritten = take_rewrite_sql ( sidemantic_rewrite (
2066+ CString :: new ( "SELECT orders.revenue FROM orders" )
2067+ . unwrap ( )
2068+ . as_ptr ( ) ,
2069+ ) ) ;
2070+ assert ! ( rewritten. contains( "SUM" ) , "{rewritten}" ) ;
2071+ assert ! ( rewritten. contains( "amount" ) , "{rewritten}" ) ;
2072+ assert ! ( !rewritten. contains( "MODEL (name customers" ) , "{rewritten}" ) ;
2073+
2074+ remove_definitions_file ( & db_path) ;
2075+ }
2076+
20112077 #[ test]
20122078 fn test_clear_resets_active_model ( ) {
20132079 let _guard = test_lock ( ) ;
0 commit comments