Commit f223261

mo khan <mo@mokhan.ca>
2026-01-09 22:46:12
refactor: do not add semicolon
1 parent 3a85631
Changed files (36)
src
tests
fixtures
basic_select
basic_select_two_columns
between_expression
case_expression
cast_expression
create_table_statement
cte
delete_statement
distinct
function_calls
in_subquery
insert_no_columns
insert_statement
is_null
join_query
multi_row_insert
multiple_and_conditions
multiple_statements
nested_expressions
new_test_example
quoted_identifiers
semicolon_addition
simple_projection
simple_select_single_line
subquery
union_query
update_statement
with_case_expression
with_cte
with_group_by_having
with_joins
with_order_by_limit
with_subquery
with_union
src/formatter.rs
@@ -31,7 +31,10 @@ fn format_query(query: &Query, indent_level: usize) -> String {
             OrderByKind::Expressions(exprs) if !exprs.is_empty() => {
                 result.push('\n');
                 result.push_str(&format!("{}ORDER BY ", " ".repeat(indent_level)));
-                let order_items: Vec<String> = exprs.iter().map(format_order_by_expr).collect();
+                let order_items: Vec<String> = exprs
+                    .iter()
+                    .map(|e| format_order_by_expr(e, indent_level))
+                    .collect();
                 result.push_str(&order_items.join(", "));
             }
             _ => {}
@@ -46,7 +49,7 @@ fn format_query(query: &Query, indent_level: usize) -> String {
                     result.push_str(&format!(
                         "{}LIMIT {}",
                         " ".repeat(indent_level),
-                        format_expr(limit)
+                        format_expr(limit, indent_level)
                     ));
                 }
             }
@@ -55,7 +58,7 @@ fn format_query(query: &Query, indent_level: usize) -> String {
                 result.push_str(&format!(
                     "{}LIMIT {}",
                     " ".repeat(indent_level),
-                    format_expr(limit)
+                    format_expr(limit, indent_level)
                 ));
             }
         }
@@ -148,7 +151,7 @@ fn format_select(select: &Select, indent_level: usize) -> String {
 
     if select.projection.len() == 1 && is_simple_projection(&select.projection[0]) {
         result.push(' ');
-        result.push_str(&format_select_item(&select.projection[0]));
+        result.push_str(&format_select_item(&select.projection[0], indent_level + 2));
     } else {
         for (i, item) in select.projection.iter().enumerate() {
             if i == 0 {
@@ -156,7 +159,11 @@ fn format_select(select: &Select, indent_level: usize) -> String {
             } else {
                 result.push_str(",\n");
             }
-            result.push_str(&format!("{}{}", item_indent, format_select_item(item)));
+            result.push_str(&format!(
+                "{}{}",
+                item_indent,
+                format_select_item(item, indent_level + 2)
+            ));
         }
     }
 
@@ -196,7 +203,10 @@ fn format_select(select: &Select, indent_level: usize) -> String {
         GroupByExpr::Expressions(exprs, _) if !exprs.is_empty() => {
             result.push('\n');
             result.push_str(&format!("{}GROUP BY ", base_indent));
-            let group_items: Vec<String> = exprs.iter().map(format_expr).collect();
+            let group_items: Vec<String> = exprs
+                .iter()
+                .map(|e| format_expr(e, indent_level))
+                .collect();
             result.push_str(&group_items.join(", "));
         }
         _ => {}
@@ -204,24 +214,28 @@ fn format_select(select: &Select, indent_level: usize) -> String {
 
     if let Some(having) = &select.having {
         result.push('\n');
-        result.push_str(&format!("{}HAVING {}", base_indent, format_expr(having)));
+        result.push_str(&format!(
+            "{}HAVING {}",
+            base_indent,
+            format_expr(having, indent_level)
+        ));
     }
 
     result
 }
 
-fn format_select_item(item: &SelectItem) -> String {
+fn format_select_item(item: &SelectItem, indent_level: usize) -> String {
     match item {
-        SelectItem::UnnamedExpr(expr) => format_expr(expr),
+        SelectItem::UnnamedExpr(expr) => format_expr(expr, indent_level),
         SelectItem::ExprWithAlias { expr, alias } => {
-            format!("{} AS {}", format_expr(expr), alias.value)
+            format!("{} AS {}", format_expr(expr, indent_level), alias.value)
         }
         SelectItem::QualifiedWildcard(kind, _) => match kind {
             SelectItemQualifiedWildcardKind::ObjectName(object_name) => {
                 format!("{}.*", object_name)
             }
             SelectItemQualifiedWildcardKind::Expr(expr) => {
-                format!("{}.*", format_expr(expr))
+                format!("{}.*", format_expr(expr, indent_level))
             }
         },
         SelectItem::Wildcard(_) => "*".to_string(),
@@ -229,21 +243,21 @@ fn format_select_item(item: &SelectItem) -> String {
 }
 
 fn format_table_with_joins(table: &TableWithJoins, indent_level: usize) -> String {
-    let mut result = format_table_factor(&table.relation);
+    let mut result = format_table_factor(&table.relation, indent_level);
 
     for join in &table.joins {
         result.push('\n');
         result.push_str(&format!(
             "{}{}",
             " ".repeat(indent_level),
-            format_join(join)
+            format_join(join, indent_level)
         ));
     }
 
     result
 }
 
-fn format_table_factor(table: &TableFactor) -> String {
+fn format_table_factor(table: &TableFactor, indent_level: usize) -> String {
     match table {
         TableFactor::Table { name, alias, .. } => {
             let mut result = name.to_string();
@@ -255,11 +269,13 @@ fn format_table_factor(table: &TableFactor) -> String {
         TableFactor::Derived {
             subquery, alias, ..
         } => {
+            let inner_indent = indent_level + 2;
             let mut result = String::new();
             result.push('(');
             result.push('\n');
-            result.push_str(&format_query(subquery, 4));
+            result.push_str(&format_query(subquery, inner_indent));
             result.push('\n');
+            result.push_str(&" ".repeat(indent_level));
             result.push(')');
             if let Some(alias) = alias {
                 result.push_str(&format!(" AS {}", alias.name.value));
@@ -270,69 +286,69 @@ fn format_table_factor(table: &TableFactor) -> String {
     }
 }
 
-fn format_join(join: &Join) -> String {
+fn format_join(join: &Join, indent_level: usize) -> String {
     let mut result = String::new();
 
     match &join.join_operator {
         JoinOperator::Join(constraint) => {
             result.push_str("JOIN ");
-            result.push_str(&format_table_factor(&join.relation));
+            result.push_str(&format_table_factor(&join.relation, indent_level));
             if let JoinConstraint::On(expr) = constraint {
-                result.push_str(&format!(" ON {}", format_expr(expr)));
+                result.push_str(&format!(" ON {}", format_expr(expr, indent_level)));
             }
         }
         JoinOperator::Inner(constraint) => {
             result.push_str("INNER JOIN ");
-            result.push_str(&format_table_factor(&join.relation));
+            result.push_str(&format_table_factor(&join.relation, indent_level));
             if let JoinConstraint::On(expr) = constraint {
-                result.push_str(&format!(" ON {}", format_expr(expr)));
+                result.push_str(&format!(" ON {}", format_expr(expr, indent_level)));
             }
         }
         JoinOperator::Left(constraint) => {
             result.push_str("LEFT OUTER JOIN ");
-            result.push_str(&format_table_factor(&join.relation));
+            result.push_str(&format_table_factor(&join.relation, indent_level));
             if let JoinConstraint::On(expr) = constraint {
-                result.push_str(&format!(" ON {}", format_expr(expr)));
+                result.push_str(&format!(" ON {}", format_expr(expr, indent_level)));
             }
         }
         JoinOperator::LeftOuter(constraint) => {
             result.push_str("LEFT OUTER JOIN ");
-            result.push_str(&format_table_factor(&join.relation));
+            result.push_str(&format_table_factor(&join.relation, indent_level));
             if let JoinConstraint::On(expr) = constraint {
-                result.push_str(&format!(" ON {}", format_expr(expr)));
+                result.push_str(&format!(" ON {}", format_expr(expr, indent_level)));
             }
         }
         JoinOperator::Right(constraint) => {
             result.push_str("RIGHT OUTER JOIN ");
-            result.push_str(&format_table_factor(&join.relation));
+            result.push_str(&format_table_factor(&join.relation, indent_level));
             if let JoinConstraint::On(expr) = constraint {
-                result.push_str(&format!(" ON {}", format_expr(expr)));
+                result.push_str(&format!(" ON {}", format_expr(expr, indent_level)));
             }
         }
         JoinOperator::RightOuter(constraint) => {
             result.push_str("RIGHT OUTER JOIN ");
-            result.push_str(&format_table_factor(&join.relation));
+            result.push_str(&format_table_factor(&join.relation, indent_level));
             if let JoinConstraint::On(expr) = constraint {
-                result.push_str(&format!(" ON {}", format_expr(expr)));
+                result.push_str(&format!(" ON {}", format_expr(expr, indent_level)));
             }
         }
         JoinOperator::FullOuter(constraint) => {
             result.push_str("FULL OUTER JOIN ");
-            result.push_str(&format_table_factor(&join.relation));
+            result.push_str(&format_table_factor(&join.relation, indent_level));
             if let JoinConstraint::On(expr) = constraint {
-                result.push_str(&format!(" ON {}", format_expr(expr)));
+                result.push_str(&format!(" ON {}", format_expr(expr, indent_level)));
             }
         }
         _ => {
             result.push_str("JOIN ");
-            result.push_str(&format_table_factor(&join.relation));
+            result.push_str(&format_table_factor(&join.relation, indent_level));
         }
     }
 
     result
 }
 
-fn format_expr(expr: &Expr) -> String {
+fn format_expr(expr: &Expr, indent_level: usize) -> String {
     match expr {
         Expr::Identifier(ident) => ident.value.clone(),
         Expr::CompoundIdentifier(idents) => idents
@@ -342,29 +358,36 @@ fn format_expr(expr: &Expr) -> String {
             .join("."),
         Expr::Value(value) => format_value(&value.value),
         Expr::BinaryOp { left, op, right } => {
-            format!("{} {} {}", format_expr(left), op, format_expr(right))
+            format!(
+                "{} {} {}",
+                format_expr(left, indent_level),
+                op,
+                format_expr(right, indent_level)
+            )
         }
         Expr::UnaryOp { op, expr } => {
-            format!("{} {}", op, format_expr(expr))
+            format!("{} {}", op, format_expr(expr, indent_level))
         }
         Expr::Cast {
             expr, data_type, ..
         } => {
-            format!("CAST({} AS {})", format_expr(expr), data_type)
+            format!("CAST({} AS {})", format_expr(expr, indent_level), data_type)
         }
         Expr::Case {
             operand,
             conditions,
             else_result,
             ..
-        } => format_case_expr(operand, conditions, else_result),
-        Expr::Function(function) => format_function(function),
+        } => format_case_expr(operand, conditions, else_result, indent_level),
+        Expr::Function(function) => format_function(function, indent_level),
         Expr::Subquery(query) => {
+            let inner_indent = indent_level + 2;
             let mut result = String::new();
             result.push('(');
             result.push('\n');
-            result.push_str(&format_query(query, 4));
+            result.push_str(&format_query(query, inner_indent));
             result.push('\n');
+            result.push_str(&" ".repeat(indent_level));
             result.push(')');
             result
         }
@@ -373,14 +396,16 @@ fn format_expr(expr: &Expr) -> String {
             subquery,
             negated,
         } => {
-            let mut result = format_expr(expr);
+            let inner_indent = indent_level + 2;
+            let mut result = format_expr(expr, indent_level);
             if *negated {
                 result.push_str(" NOT");
             }
             result.push_str(" IN (");
             result.push('\n');
-            result.push_str(&format_query(subquery, 4));
+            result.push_str(&format_query(subquery, inner_indent));
             result.push('\n');
+            result.push_str(&" ".repeat(indent_level));
             result.push(')');
             result
         }
@@ -390,14 +415,14 @@ fn format_expr(expr: &Expr) -> String {
             low,
             high,
         } => {
-            let mut result = format_expr(expr);
+            let mut result = format_expr(expr, indent_level);
             if *negated {
                 result.push_str(" NOT");
             }
             result.push_str(&format!(
                 " BETWEEN {} AND {}",
-                format_expr(low),
-                format_expr(high)
+                format_expr(low, indent_level),
+                format_expr(high, indent_level)
             ));
             result
         }
@@ -407,16 +432,16 @@ fn format_expr(expr: &Expr) -> String {
             pattern,
             ..
         } => {
-            let mut result = format_expr(expr);
+            let mut result = format_expr(expr, indent_level);
             if *negated {
                 result.push_str(" NOT");
             }
-            result.push_str(&format!(" LIKE {}", format_expr(pattern)));
+            result.push_str(&format!(" LIKE {}", format_expr(pattern, indent_level)));
             result
         }
-        Expr::IsNull(expr) => format!("{} IS NULL", format_expr(expr)),
-        Expr::IsNotNull(expr) => format!("{} IS NOT NULL", format_expr(expr)),
-        Expr::Nested(expr) => format!("({})", format_expr(expr)),
+        Expr::IsNull(expr) => format!("{} IS NULL", format_expr(expr, indent_level)),
+        Expr::IsNotNull(expr) => format!("{} IS NOT NULL", format_expr(expr, indent_level)),
+        Expr::Nested(expr) => format!("({})", format_expr(expr, indent_level)),
         _ => expr.to_string(),
     }
 }
@@ -425,31 +450,38 @@ fn format_case_expr(
     operand: &Option<Box<Expr>>,
     conditions: &Vec<CaseWhen>,
     else_result: &Option<Box<Expr>>,
+    indent_level: usize,
 ) -> String {
     let mut result = String::new();
+    let inner_indent = " ".repeat(indent_level + 2);
 
     result.push_str("CASE");
     if let Some(operand) = operand {
-        result.push_str(&format!(" {}", format_expr(operand)));
+        result.push_str(&format!(" {}", format_expr(operand, indent_level)));
     }
 
     for condition in conditions {
         result.push_str(&format!(
-            "\n  WHEN {} THEN {}",
-            format_expr(&condition.condition),
-            format_expr(&condition.result)
+            "\n{}WHEN {} THEN {}",
+            inner_indent,
+            format_expr(&condition.condition, indent_level + 2),
+            format_expr(&condition.result, indent_level + 2)
         ));
     }
 
     if let Some(else_result) = else_result {
-        result.push_str(&format!("\n  ELSE {}", format_expr(else_result)));
+        result.push_str(&format!(
+            "\n{}ELSE {}",
+            inner_indent,
+            format_expr(else_result, indent_level + 2)
+        ));
     }
 
-    result.push_str("\nEND");
+    result.push_str(&format!("\n{}END", " ".repeat(indent_level)));
     result
 }
 
-fn format_function(function: &Function) -> String {
+fn format_function(function: &Function, indent_level: usize) -> String {
     let mut result = function.name.to_string().to_uppercase();
     result.push('(');
 
@@ -461,17 +493,32 @@ fn format_function(function: &Function) -> String {
 
     let args: Vec<String> = match &function.args {
         FunctionArguments::None => vec![],
-        FunctionArguments::Subquery(_) => vec!["SUBQUERY".to_string()],
+        FunctionArguments::Subquery(subquery) => {
+            let inner_indent = indent_level + 2;
+            vec![format!(
+                "\n{}\n{}",
+                format_query(subquery, inner_indent),
+                " ".repeat(indent_level)
+            )]
+        }
         FunctionArguments::List(list) => list
             .args
             .iter()
             .map(|arg| match arg {
                 FunctionArg::Named { name, arg, .. } => {
-                    format!("{} => {}", name.value, format_function_arg_expr(arg))
+                    format!(
+                        "{} => {}",
+                        name.value,
+                        format_function_arg_expr(arg, indent_level)
+                    )
                 }
-                FunctionArg::Unnamed(arg) => format_function_arg_expr(arg),
+                FunctionArg::Unnamed(arg) => format_function_arg_expr(arg, indent_level),
                 FunctionArg::ExprNamed { name, arg, .. } => {
-                    format!("{} => {}", format_expr(name), format_function_arg_expr(arg))
+                    format!(
+                        "{} => {}",
+                        format_expr(name, indent_level),
+                        format_function_arg_expr(arg, indent_level)
+                    )
                 }
             })
             .collect(),
@@ -483,9 +530,17 @@ fn format_function(function: &Function) -> String {
     result
 }
 
-fn format_function_arg_expr(arg: &FunctionArgExpr) -> String {
+fn format_function_arg_expr(arg: &FunctionArgExpr, indent_level: usize) -> String {
     match arg {
-        FunctionArgExpr::Expr(expr) => format_expr(expr),
+        FunctionArgExpr::Expr(Expr::Subquery(query)) => {
+            let inner_indent = indent_level + 2;
+            format!(
+                "(\n{}\n{})",
+                format_query(query, inner_indent),
+                " ".repeat(indent_level)
+            )
+        }
+        FunctionArgExpr::Expr(expr) => format_expr(expr, indent_level),
         FunctionArgExpr::QualifiedWildcard(name) => format!("{}.*", name),
         FunctionArgExpr::Wildcard => "*".to_string(),
     }
@@ -502,8 +557,8 @@ fn format_value(value: &Value) -> String {
     }
 }
 
-fn format_order_by_expr(order: &OrderByExpr) -> String {
-    let mut result = format_expr(&order.expr);
+fn format_order_by_expr(order: &OrderByExpr, indent_level: usize) -> String {
+    let mut result = format_expr(&order.expr, indent_level);
 
     if let Some(asc) = order.options.asc {
         if asc {
@@ -552,7 +607,7 @@ fn format_update(
                 AssignmentTarget::ColumnName(object_name) => object_name.to_string(),
                 _ => "UNKNOWN".to_string(),
             },
-            format_expr(&assignment.value)
+            format_expr(&assignment.value, indent_level + 2)
         ));
     }
 
@@ -598,7 +653,7 @@ fn format_where_expr(expr: &Expr, indent_level: usize) -> String {
                 right_str
             )
         }
-        _ => format_expr(expr),
+        _ => format_expr(expr, indent_level),
     }
 }
 
@@ -661,7 +716,7 @@ mod tests {
     fn test_select_with_subquery() {
         let input =
             "SELECT * FROM (SELECT id, name FROM users WHERE active = true) AS active_users";
-        let expected = "SELECT *\nFROM\n  (\n    SELECT\n      id,\n      name\n    FROM\n      users\n    WHERE active = TRUE\n) AS active_users";
+        let expected = "SELECT *\nFROM\n  (\n    SELECT\n      id,\n      name\n    FROM\n      users\n    WHERE active = TRUE\n  ) AS active_users";
         assert_eq!(parse_and_format(input), expected);
     }
 
@@ -669,7 +724,7 @@ mod tests {
     fn test_select_with_case_expression() {
         let input =
             "SELECT CASE WHEN age < 18 THEN 'minor' ELSE 'adult' END AS age_group FROM users";
-        let expected = "SELECT\n  CASE\n  WHEN age < 18 THEN 'minor'\n  ELSE 'adult'\nEND AS age_group\nFROM\n  users";
+        let expected = "SELECT\n  CASE\n    WHEN age < 18 THEN 'minor'\n    ELSE 'adult'\n  END AS age_group\nFROM\n  users";
         assert_eq!(parse_and_format(input), expected);
     }
 
@@ -727,7 +782,7 @@ mod tests {
     fn test_in_subquery() {
         let input = "SELECT * FROM users WHERE id IN (SELECT user_id FROM orders)";
         let expected =
-            "SELECT *\nFROM\n  users\nWHERE id IN (\n    SELECT user_id\n    FROM\n      orders\n)";
+            "SELECT *\nFROM\n  users\nWHERE id IN (\n    SELECT user_id\n    FROM\n      orders\n  )";
         assert_eq!(parse_and_format(input), expected);
     }
 
@@ -771,7 +826,7 @@ mod tests {
     fn test_complex_case_expression() {
         let input =
             "SELECT CASE status WHEN 'active' THEN 1 WHEN 'inactive' THEN 0 ELSE -1 END FROM users";
-        let expected = "SELECT\n  CASE status\n  WHEN 'active' THEN 1\n  WHEN 'inactive' THEN 0\n  ELSE - 1\nEND\nFROM\n  users";
+        let expected = "SELECT\n  CASE status\n    WHEN 'active' THEN 1\n    WHEN 'inactive' THEN 0\n    ELSE - 1\n  END\nFROM\n  users";
         assert_eq!(parse_and_format(input), expected);
     }
 }
@@ -841,20 +896,24 @@ fn format_delete(delete: &Delete, indent_level: usize) -> String {
 }
 
 fn format_create_table(create_table: &CreateTable, indent_level: usize) -> String {
-    let mut result = format!("{}CREATE TABLE {} (", " ".repeat(indent_level), create_table.name);
+    let mut result = format!(
+        "{}CREATE TABLE {} (",
+        " ".repeat(indent_level),
+        create_table.name
+    );
 
     result.push_str(&format_indented_list(
         &create_table.columns,
-        format_column_def,
+        |col| format_column_def(col, indent_level + 2),
         indent_level,
-        true
+        true,
     ));
 
     result.push(')');
     result
 }
 
-fn format_column_def(column: &ColumnDef) -> String {
+fn format_column_def(column: &ColumnDef, indent_level: usize) -> String {
     let mut result = format!("{} {}", column.name.value, column.data_type);
 
     for option in &column.options {
@@ -862,7 +921,7 @@ fn format_column_def(column: &ColumnDef) -> String {
             ColumnOption::NotNull => result.push_str(" NOT NULL"),
             ColumnOption::Null => result.push_str(" NULL"),
             ColumnOption::Default(expr) => {
-                result.push_str(&format!(" DEFAULT {}", format_expr(expr)));
+                result.push_str(&format!(" DEFAULT {}", format_expr(expr, indent_level)));
             }
             ColumnOption::Unique { is_primary, .. } => {
                 if *is_primary {
@@ -928,7 +987,7 @@ where
 
 fn format_values_row(row: &[Expr], indent_level: usize) -> String {
     if row.len() == 1 {
-        format!("({})", format_expr(&row[0]))
+        format!("({})", format_expr(&row[0], indent_level))
     } else {
         let mut result = String::from("(");
         result.push('\n');
@@ -936,10 +995,14 @@ fn format_values_row(row: &[Expr], indent_level: usize) -> String {
             if i > 0 {
                 result.push_str(",\n");
             }
-            result.push_str(&format!("{}  {}", " ".repeat(indent_level), format_expr(value)));
+            result.push_str(&format!(
+                "{}  {}",
+                " ".repeat(indent_level),
+                format_expr(value, indent_level + 2)
+            ));
         }
         result.push('\n');
-        result.push_str(&format!("{}", " ".repeat(indent_level)));
+        result.push_str(&" ".repeat(indent_level));
         result.push(')');
         result
     }
src/main.rs
@@ -25,6 +25,8 @@ fn run() -> Result<()> {
         return Ok(());
     }
 
+    let has_semicolon = input.ends_with(';');
+
     let dialect = GenericDialect {};
     match Parser::parse_sql(&dialect, input) {
         Ok(statements) => {
@@ -35,8 +37,11 @@ fn run() -> Result<()> {
                 }
                 output.push(format_statement(statement, 0));
             }
-            let formatted = output.join("");
-            let formatted = ensure_semicolon_and_cleanup(&formatted);
+            let mut formatted = output.join("");
+            formatted = cleanup_whitespace(&formatted);
+            if has_semicolon {
+                formatted.push(';');
+            }
             println!("{}", formatted);
             Ok(())
         }
@@ -50,14 +55,8 @@ fn run() -> Result<()> {
     }
 }
 
-fn ensure_semicolon_and_cleanup(sql: &str) -> String {
-    let mut result = sql.trim_end().to_string();
-
-    if !result.ends_with(';') {
-        result.push(';');
-    }
-
-    result
+fn cleanup_whitespace(sql: &str) -> String {
+    sql.trim_end()
         .lines()
         .map(|line| line.trim_end())
         .collect::<Vec<_>>()
tests/fixtures/basic_select/output.sql
@@ -4,4 +4,4 @@ SELECT
   email
 FROM
   users
-WHERE active = TRUE;
\ No newline at end of file
+WHERE active = TRUE
\ No newline at end of file
tests/fixtures/basic_select_two_columns/output.sql
@@ -3,4 +3,4 @@ SELECT
   name
 FROM
   users
-WHERE active = TRUE;
\ No newline at end of file
+WHERE active = TRUE
\ No newline at end of file
tests/fixtures/between_expression/output.sql
@@ -1,4 +1,4 @@
 SELECT *
 FROM
   products
-WHERE price BETWEEN 10 AND 100;
\ No newline at end of file
+WHERE price BETWEEN 10 AND 100
\ No newline at end of file
tests/fixtures/case_expression/output.sql
@@ -1,8 +1,8 @@
 SELECT
   CASE
-  WHEN age < 18 THEN 'minor'
-  WHEN age >= 65 THEN 'senior'
-  ELSE 'adult'
-END AS age_group
+    WHEN age < 18 THEN 'minor'
+    WHEN age >= 65 THEN 'senior'
+    ELSE 'adult'
+  END AS age_group
 FROM
-  users;
\ No newline at end of file
+  users
\ No newline at end of file
tests/fixtures/cast_expression/output.sql
@@ -1,4 +1,4 @@
 SELECT
   CAST(id AS VARCHAR)
 FROM
-  users;
\ No newline at end of file
+  users
\ No newline at end of file
tests/fixtures/create_table_statement/output.sql
@@ -3,4 +3,4 @@ CREATE TABLE users (
   name VARCHAR(100) NOT NULL,
   email VARCHAR(255) UNIQUE,
   active BOOLEAN DEFAULT TRUE
-);
\ No newline at end of file
+)
\ No newline at end of file
tests/fixtures/cte/output.sql
@@ -7,4 +7,4 @@ WITH
   )
 SELECT *
 FROM
-  active_users;
\ No newline at end of file
+  active_users
\ No newline at end of file
tests/fixtures/delete_statement/output.sql
@@ -1,3 +1,3 @@
 DELETE FROM users
 WHERE active = FALSE
-  AND last_login < '2020-01-01';
\ No newline at end of file
+  AND last_login < '2020-01-01'
\ No newline at end of file
tests/fixtures/distinct/output.sql
@@ -1,3 +1,3 @@
 SELECT DISTINCT department
 FROM
-  employees;
\ No newline at end of file
+  employees
\ No newline at end of file
tests/fixtures/function_calls/output.sql
@@ -3,4 +3,4 @@ SELECT
   MAX(age),
   UPPER(name)
 FROM
-  users;
\ No newline at end of file
+  users
\ No newline at end of file
tests/fixtures/in_subquery/output.sql
@@ -5,4 +5,4 @@ WHERE id IN (
     SELECT user_id
     FROM
       orders
-);
\ No newline at end of file
+  )
\ No newline at end of file
tests/fixtures/insert_no_columns/output.sql
@@ -4,4 +4,4 @@ VALUES (
   'John Doe',
   'john@example.com',
   TRUE
-);
\ No newline at end of file
+)
\ No newline at end of file
tests/fixtures/insert_statement/output.sql
@@ -9,4 +9,4 @@ VALUES (
   'John Doe',
   'john@example.com',
   TRUE
-);
\ No newline at end of file
+)
\ No newline at end of file
tests/fixtures/is_null/output.sql
@@ -1,4 +1,4 @@
 SELECT *
 FROM
   users
-WHERE email IS NOT NULL;
\ No newline at end of file
+WHERE email IS NOT NULL
\ No newline at end of file
tests/fixtures/join_query/output.sql
@@ -3,4 +3,4 @@ SELECT
   p.title
 FROM
   users AS u
-  INNER JOIN posts AS p ON u.id = p.user_id;
\ No newline at end of file
+  INNER JOIN posts AS p ON u.id = p.user_id
\ No newline at end of file
tests/fixtures/multi_row_insert/output.sql
@@ -17,4 +17,4 @@ VALUES (
   3,
   'Bob',
   'bob@example.com'
-);
\ No newline at end of file
+)
\ No newline at end of file
tests/fixtures/multiple_and_conditions/output.sql
@@ -3,4 +3,4 @@ FROM
   users
 WHERE active = TRUE
   AND age > 18
-  AND name LIKE 'A%';
\ No newline at end of file
+  AND name LIKE 'A%'
\ No newline at end of file
tests/fixtures/multiple_statements/output.sql
@@ -3,4 +3,4 @@ FROM
   users
 SELECT *
 FROM
-  posts;
\ No newline at end of file
+  posts
\ No newline at end of file
tests/fixtures/nested_expressions/output.sql
@@ -1,4 +1,4 @@
 SELECT *
 FROM
   users
-WHERE (active = TRUE AND age > 18) OR role = 'admin';
\ No newline at end of file
+WHERE (active = TRUE AND age > 18) OR role = 'admin'
\ No newline at end of file
tests/fixtures/new_test_example/output.sql
@@ -4,4 +4,4 @@ SELECT
 FROM
   users
 GROUP BY department
-HAVING COUNT(*) > 5;
\ No newline at end of file
+HAVING COUNT(*) > 5
\ No newline at end of file
tests/fixtures/quoted_identifiers/output.sql
@@ -3,4 +3,4 @@ SELECT
   user_name
 FROM
   "admin_users"
-WHERE active = TRUE;
\ No newline at end of file
+WHERE active = TRUE
\ No newline at end of file
tests/fixtures/semicolon_addition/output.sql
@@ -1,3 +1,3 @@
 SELECT *
 FROM
-  users;
\ No newline at end of file
+  users
\ No newline at end of file
tests/fixtures/simple_projection/output.sql
@@ -1,3 +1,3 @@
 SELECT 1 AS one
 FROM
-  users;
\ No newline at end of file
+  users
\ No newline at end of file
tests/fixtures/simple_select_single_line/output.sql
@@ -1,3 +1,3 @@
 SELECT 1 AS one
 FROM
-  users;
\ No newline at end of file
+  users
\ No newline at end of file
tests/fixtures/subquery/output.sql
@@ -7,5 +7,5 @@ FROM
     FROM
       users
     WHERE active = TRUE
-) AS active_users
-WHERE name LIKE 'A%';
\ No newline at end of file
+  ) AS active_users
+WHERE name LIKE 'A%'
\ No newline at end of file
tests/fixtures/union_query/output.sql
@@ -4,4 +4,4 @@ FROM
 UNION
 SELECT id
 FROM
-  customers;
\ No newline at end of file
+  customers
\ No newline at end of file
tests/fixtures/update_statement/output.sql
@@ -4,4 +4,4 @@ SET
   email = 'john.smith@example.com',
   last_updated = NOW()
 WHERE id = 1
-  AND active = TRUE;
\ No newline at end of file
+  AND active = TRUE
\ No newline at end of file
tests/fixtures/with_case_expression/output.sql
@@ -1,7 +1,7 @@
 SELECT
   CASE
-  WHEN age < 18 THEN 'minor'
-  ELSE 'adult'
-END AS age_group
+    WHEN age < 18 THEN 'minor'
+    ELSE 'adult'
+  END AS age_group
 FROM
-  users;
\ No newline at end of file
+  users
\ No newline at end of file
tests/fixtures/with_cte/output.sql
@@ -7,4 +7,4 @@ WITH
   )
 SELECT *
 FROM
-  active_users;
\ No newline at end of file
+  active_users
\ No newline at end of file
tests/fixtures/with_group_by_having/output.sql
@@ -4,4 +4,4 @@ SELECT
 FROM
   employees
 GROUP BY department
-HAVING COUNT(*) > 5;
\ No newline at end of file
+HAVING COUNT(*) > 5
\ No newline at end of file
tests/fixtures/with_joins/output.sql
@@ -3,4 +3,4 @@ SELECT
   p.title
 FROM
   users AS u
-  INNER JOIN posts AS p ON u.id = p.user_id;
\ No newline at end of file
+  INNER JOIN posts AS p ON u.id = p.user_id
\ No newline at end of file
tests/fixtures/with_order_by_limit/output.sql
@@ -2,4 +2,4 @@ SELECT *
 FROM
   users
 ORDER BY name ASC
-LIMIT 10;
\ No newline at end of file
+LIMIT 10
\ No newline at end of file
tests/fixtures/with_subquery/output.sql
@@ -7,4 +7,4 @@ FROM
     FROM
       users
     WHERE active = TRUE
-) AS active_users;
\ No newline at end of file
+  ) AS active_users
\ No newline at end of file
tests/fixtures/with_union/output.sql
@@ -4,4 +4,4 @@ FROM
 UNION
 SELECT id
 FROM
-  customers;
\ No newline at end of file
+  customers
\ No newline at end of file