Commit 3a85631

mo khan <mo@mokhan.ca>
2025-09-25 17:16:33
test: add fixtures for inserts and updates
1 parent e018ad6
Changed files (7)
src
tests
fixtures
insert_no_columns
multi_row_insert
update_statement
src/formatter.rs
@@ -561,7 +561,7 @@ fn format_update(
         result.push_str(&format!(
             "{}WHERE {}",
             " ".repeat(indent_level),
-            format_expr(selection)
+            format_where_expr(selection, indent_level + 2)
         ));
     }
 
@@ -779,23 +779,7 @@ mod tests {
 fn format_insert(insert: &Insert, indent_level: usize) -> String {
     let mut result = format!("{}INSERT INTO {}", " ".repeat(indent_level), insert.table);
 
-    if !insert.columns.is_empty() {
-        result.push_str(" (");
-        if insert.columns.len() == 1 {
-            result.push_str(&insert.columns[0].value);
-        } else {
-            result.push('\n');
-            for (i, column) in insert.columns.iter().enumerate() {
-                if i > 0 {
-                    result.push_str(",\n");
-                }
-                result.push_str(&format!("{}  {}", " ".repeat(indent_level), column.value));
-            }
-            result.push('\n');
-            result.push_str(&format!("{}", " ".repeat(indent_level)));
-        }
-        result.push(')');
-    }
+    result.push_str(&format_column_list(&insert.columns, indent_level));
 
     if let Some(source) = &insert.source {
         result.push('\n');
@@ -804,27 +788,10 @@ fn format_insert(insert: &Insert, indent_level: usize) -> String {
             for (i, row) in values.rows.iter().enumerate() {
                 if i > 0 {
                     result.push_str(",\n");
-                    result.push_str(&format!("{}      ", " ".repeat(indent_level)));
-                } else {
-                    result.push_str(" (");
-                    if row.len() > 1 {
-                        result.push('\n');
-                    }
-                }
-
-                if row.len() == 1 {
-                    result.push_str(&format_expr(&row[0]));
                 } else {
-                    for (j, value) in row.iter().enumerate() {
-                        if j > 0 {
-                            result.push_str(",\n");
-                        }
-                        result.push_str(&format!("{}  {}", " ".repeat(indent_level), format_expr(value)));
-                    }
-                    result.push('\n');
-                    result.push_str(&format!("{}", " ".repeat(indent_level)));
+                    result.push(' ');
                 }
-                result.push(')');
+                result.push_str(&format_values_row(row, indent_level));
             }
         }
     }
@@ -876,19 +843,12 @@ 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);
 
-    if create_table.columns.len() == 1 {
-        result.push_str(&format_column_def(&create_table.columns[0]));
-    } else {
-        result.push('\n');
-        for (i, column) in create_table.columns.iter().enumerate() {
-            if i > 0 {
-                result.push_str(",\n");
-            }
-            result.push_str(&format!("{}  {}", " ".repeat(indent_level), format_column_def(column)));
-        }
-        result.push('\n');
-        result.push_str(&format!("{}", " ".repeat(indent_level)));
-    }
+    result.push_str(&format_indented_list(
+        &create_table.columns,
+        format_column_def,
+        indent_level,
+        true
+    ));
 
     result.push(')');
     result
@@ -917,3 +877,70 @@ fn format_column_def(column: &ColumnDef) -> String {
 
     result
 }
+
+fn format_column_list(columns: &[Ident], indent_level: usize) -> String {
+    if columns.is_empty() {
+        return String::new();
+    }
+
+    if columns.len() == 1 {
+        format!(" ({})", columns[0].value)
+    } else {
+        let mut result = String::from(" (");
+        result.push('\n');
+        for (i, column) in columns.iter().enumerate() {
+            if i > 0 {
+                result.push_str(",\n");
+            }
+            result.push_str(&format!("{}  {}", " ".repeat(indent_level), column.value));
+        }
+        result.push('\n');
+        result.push_str(&format!("{}", " ".repeat(indent_level)));
+        result.push(')');
+        result
+    }
+}
+
+fn format_indented_list<T, F>(items: &[T], formatter: F, indent_level: usize, single_line: bool) -> String
+where
+    F: Fn(&T) -> String,
+{
+    if items.is_empty() {
+        return String::new();
+    }
+
+    if items.len() == 1 && single_line {
+        formatter(&items[0])
+    } else {
+        let mut result = String::new();
+        result.push('\n');
+        for (i, item) in items.iter().enumerate() {
+            if i > 0 {
+                result.push_str(",\n");
+            }
+            result.push_str(&format!("{}  {}", " ".repeat(indent_level), formatter(item)));
+        }
+        result.push('\n');
+        result.push_str(&format!("{}", " ".repeat(indent_level)));
+        result
+    }
+}
+
+fn format_values_row(row: &[Expr], indent_level: usize) -> String {
+    if row.len() == 1 {
+        format!("({})", format_expr(&row[0]))
+    } else {
+        let mut result = String::from("(");
+        result.push('\n');
+        for (i, value) in row.iter().enumerate() {
+            if i > 0 {
+                result.push_str(",\n");
+            }
+            result.push_str(&format!("{}  {}", " ".repeat(indent_level), format_expr(value)));
+        }
+        result.push('\n');
+        result.push_str(&format!("{}", " ".repeat(indent_level)));
+        result.push(')');
+        result
+    }
+}
tests/fixtures/insert_no_columns/input.sql
@@ -0,0 +1,1 @@
+INSERT INTO users VALUES (1, 'John Doe', 'john@example.com', true)
\ No newline at end of file
tests/fixtures/insert_no_columns/output.sql
@@ -0,0 +1,7 @@
+INSERT INTO users
+VALUES (
+  1,
+  'John Doe',
+  'john@example.com',
+  TRUE
+);
\ No newline at end of file
tests/fixtures/multi_row_insert/input.sql
@@ -0,0 +1,1 @@
+INSERT INTO users (id, name, email) VALUES (1, 'John', 'john@example.com'), (2, 'Jane', 'jane@example.com'), (3, 'Bob', 'bob@example.com')
\ No newline at end of file
tests/fixtures/multi_row_insert/output.sql
@@ -0,0 +1,20 @@
+INSERT INTO users (
+  id,
+  name,
+  email
+)
+VALUES (
+  1,
+  'John',
+  'john@example.com'
+),
+(
+  2,
+  'Jane',
+  'jane@example.com'
+),
+(
+  3,
+  'Bob',
+  'bob@example.com'
+);
\ No newline at end of file
tests/fixtures/update_statement/input.sql
@@ -0,0 +1,1 @@
+UPDATE users SET name = 'John Smith', email = 'john.smith@example.com', last_updated = NOW() WHERE id = 1 AND active = true
\ No newline at end of file
tests/fixtures/update_statement/output.sql
@@ -0,0 +1,7 @@
+UPDATE users
+SET
+  name = 'John Smith',
+  email = 'john.smith@example.com',
+  last_updated = NOW()
+WHERE id = 1
+  AND active = TRUE;
\ No newline at end of file