summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoão Baptista <15786310+M4RC3L05@users.noreply.github.com>2024-11-19 21:01:16 +0000
committerGitHub <noreply@github.com>2024-11-19 21:01:16 +0000
commitc55e936be03a3a023330789f903e2fbd12f4a308 (patch)
tree0dc406b0cfb82a6c0683edb9152c6450aa3abf52
parent628816448ea45807762fd8eb0c59302c9f2aac9a (diff)
feat(fmt): support SQL (#26750)
This commit adds support for .sql files in "deno fmt" subcommand. Closes: https://github.com/denoland/deno/issues/25024 --------- Signed-off-by: m4rc3l05 <15786310+M4RC3L05@users.noreply.github.com> Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
-rw-r--r--Cargo.lock12
-rw-r--r--cli/Cargo.toml2
-rw-r--r--cli/args/flags.rs27
-rw-r--r--cli/args/mod.rs4
-rw-r--r--cli/lsp/language_server.rs3
-rw-r--r--cli/schemas/config-file.v1.json1
-rw-r--r--cli/tools/fmt.rs64
-rw-r--r--tests/integration/fmt_tests.rs18
-rw-r--r--tests/specs/fmt/sql/__test__.jsonc25
-rw-r--r--tests/specs/fmt/sql/badly_formatted.sql1
-rw-r--r--tests/specs/fmt/sql/ignore_file.sql3
-rw-r--r--tests/specs/fmt/sql/ignore_file2.sql3
-rw-r--r--tests/specs/fmt/sql/ignore_file3.sql6
-rw-r--r--tests/specs/fmt/sql/ignore_file4.sql3
-rw-r--r--tests/specs/fmt/sql/well_formatted.sql4
-rw-r--r--tests/specs/fmt/sql/wrong_file_ignore.sql6
-rw-r--r--tests/testdata/fmt/badly_formatted.md12
-rw-r--r--tests/testdata/fmt/badly_formatted.sql21
-rw-r--r--tests/testdata/fmt/badly_formatted_fixed.md15
-rw-r--r--tests/testdata/fmt/badly_formatted_fixed.sql22
20 files changed, 247 insertions, 5 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 5705acccc..1a16714bb 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1291,6 +1291,7 @@ dependencies = [
"sha2",
"shell-escape",
"spki",
+ "sqlformat",
"strsim",
"tar",
"tempfile",
@@ -6795,6 +6796,17 @@ dependencies = [
]
[[package]]
+name = "sqlformat"
+version = "0.3.1"
+source = "git+https://github.com/shssoichiro/sqlformat-rs.git?rev=827d639#827d639bef94d8e5a5a0e29b41185c8d572f24e6"
+dependencies = [
+ "nom 7.1.3",
+ "once_cell",
+ "regex",
+ "unicode_categories",
+]
+
+[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/cli/Cargo.toml b/cli/Cargo.toml
index dd1d44a8e..16f39e9d4 100644
--- a/cli/Cargo.toml
+++ b/cli/Cargo.toml
@@ -151,6 +151,8 @@ serde_repr.workspace = true
sha2.workspace = true
shell-escape = "=0.1.5"
spki = { version = "0.7", features = ["pem"] }
+# NOTE(bartlomieju): for now using github URL, because 0.3.2 with important fixes hasn't been released yet.
+sqlformat = { git = "https://github.com/shssoichiro/sqlformat-rs.git", rev = "827d639" }
strsim = "0.11.1"
tar.workspace = true
tempfile.workspace = true
diff --git a/cli/args/flags.rs b/cli/args/flags.rs
index 39db12b5f..262bc0468 100644
--- a/cli/args/flags.rs
+++ b/cli/args/flags.rs
@@ -210,6 +210,7 @@ pub struct FmtFlags {
pub no_semicolons: Option<bool>,
pub watch: Option<WatchFlags>,
pub unstable_component: bool,
+ pub unstable_sql: bool,
}
impl FmtFlags {
@@ -2291,7 +2292,7 @@ Ignore formatting a file by adding an ignore comment at the top of the file:
.value_parser([
"ts", "tsx", "js", "jsx", "md", "json", "jsonc", "css", "scss",
"sass", "less", "html", "svelte", "vue", "astro", "yml", "yaml",
- "ipynb",
+ "ipynb", "sql"
])
.help_heading(FMT_HEADING).requires("files"),
)
@@ -2410,6 +2411,14 @@ Ignore formatting a file by adding an ignore comment at the top of the file:
.help_heading(FMT_HEADING)
.hide(true),
)
+ .arg(
+ Arg::new("unstable-sql")
+ .long("unstable-sql")
+ .help("Enable formatting SQL files.")
+ .value_parser(FalseyValueParser::new())
+ .action(ArgAction::SetTrue)
+ .help_heading(FMT_HEADING),
+ )
})
}
@@ -4634,6 +4643,7 @@ fn fmt_parse(
let prose_wrap = matches.remove_one::<String>("prose-wrap");
let no_semicolons = matches.remove_one::<bool>("no-semicolons");
let unstable_component = matches.get_flag("unstable-component");
+ let unstable_sql = matches.get_flag("unstable-sql");
flags.subcommand = DenoSubcommand::Fmt(FmtFlags {
check: matches.get_flag("check"),
@@ -4646,6 +4656,7 @@ fn fmt_parse(
no_semicolons,
watch: watch_arg_parse(matches)?,
unstable_component,
+ unstable_sql,
});
Ok(())
}
@@ -6565,6 +6576,7 @@ mod tests {
prose_wrap: None,
no_semicolons: None,
unstable_component: false,
+ unstable_sql: false,
watch: Default::default(),
}),
..Flags::default()
@@ -6588,6 +6600,7 @@ mod tests {
prose_wrap: None,
no_semicolons: None,
unstable_component: false,
+ unstable_sql: false,
watch: Default::default(),
}),
..Flags::default()
@@ -6611,6 +6624,7 @@ mod tests {
prose_wrap: None,
no_semicolons: None,
unstable_component: false,
+ unstable_sql: false,
watch: Default::default(),
}),
..Flags::default()
@@ -6634,6 +6648,7 @@ mod tests {
prose_wrap: None,
no_semicolons: None,
unstable_component: false,
+ unstable_sql: false,
watch: Some(Default::default()),
}),
..Flags::default()
@@ -6648,7 +6663,8 @@ mod tests {
"--unstable-css",
"--unstable-html",
"--unstable-component",
- "--unstable-yaml"
+ "--unstable-yaml",
+ "--unstable-sql"
]);
assert_eq!(
r.unwrap(),
@@ -6666,6 +6682,7 @@ mod tests {
prose_wrap: None,
no_semicolons: None,
unstable_component: true,
+ unstable_sql: true,
watch: Some(WatchFlags {
hmr: false,
no_clear_screen: true,
@@ -6700,6 +6717,7 @@ mod tests {
prose_wrap: None,
no_semicolons: None,
unstable_component: false,
+ unstable_sql: false,
watch: Some(Default::default()),
}),
..Flags::default()
@@ -6723,6 +6741,7 @@ mod tests {
prose_wrap: None,
no_semicolons: None,
unstable_component: false,
+ unstable_sql: false,
watch: Default::default(),
}),
config_flag: ConfigFlag::Path("deno.jsonc".to_string()),
@@ -6754,6 +6773,7 @@ mod tests {
prose_wrap: None,
no_semicolons: None,
unstable_component: false,
+ unstable_sql: false,
watch: Some(Default::default()),
}),
config_flag: ConfigFlag::Path("deno.jsonc".to_string()),
@@ -6790,6 +6810,7 @@ mod tests {
prose_wrap: Some("never".to_string()),
no_semicolons: Some(true),
unstable_component: false,
+ unstable_sql: false,
watch: Default::default(),
}),
..Flags::default()
@@ -6820,6 +6841,7 @@ mod tests {
prose_wrap: None,
no_semicolons: Some(false),
unstable_component: false,
+ unstable_sql: false,
watch: Default::default(),
}),
..Flags::default()
@@ -6845,6 +6867,7 @@ mod tests {
prose_wrap: None,
no_semicolons: None,
unstable_component: false,
+ unstable_sql: false,
watch: Default::default(),
}),
ext: Some("html".to_string()),
diff --git a/cli/args/mod.rs b/cli/args/mod.rs
index ec75d7a10..61e1443a7 100644
--- a/cli/args/mod.rs
+++ b/cli/args/mod.rs
@@ -289,6 +289,7 @@ impl BenchOptions {
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
pub struct UnstableFmtOptions {
pub component: bool,
+ pub sql: bool,
}
#[derive(Clone, Debug)]
@@ -322,6 +323,7 @@ impl FmtOptions {
options: resolve_fmt_options(fmt_flags, fmt_config.options),
unstable: UnstableFmtOptions {
component: unstable.component || fmt_flags.unstable_component,
+ sql: unstable.sql || fmt_flags.unstable_sql,
},
files: fmt_config.files,
}
@@ -1319,6 +1321,7 @@ impl CliOptions {
let workspace = self.workspace();
UnstableFmtOptions {
component: workspace.has_unstable("fmt-component"),
+ sql: workspace.has_unstable("fmt-sql"),
}
}
@@ -1667,6 +1670,7 @@ impl CliOptions {
"byonm",
"bare-node-builtins",
"fmt-component",
+ "fmt-sql",
])
.collect();
diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs
index 2ce26c1f2..cbe194e14 100644
--- a/cli/lsp/language_server.rs
+++ b/cli/lsp/language_server.rs
@@ -1405,6 +1405,9 @@ impl Inner {
component: config_data
.map(|d| d.unstable.contains("fmt-component"))
.unwrap_or(false),
+ sql: config_data
+ .map(|d| d.unstable.contains("fmt-sql"))
+ .unwrap_or(false),
};
let document = document.clone();
move || {
diff --git a/cli/schemas/config-file.v1.json b/cli/schemas/config-file.v1.json
index 3ba803ef8..ccd773efb 100644
--- a/cli/schemas/config-file.v1.json
+++ b/cli/schemas/config-file.v1.json
@@ -557,6 +557,7 @@
"ffi",
"fs",
"fmt-component",
+ "fmt-sql",
"http",
"kv",
"net",
diff --git a/cli/tools/fmt.rs b/cli/tools/fmt.rs
index d40abd5f5..9c2c70912 100644
--- a/cli/tools/fmt.rs
+++ b/cli/tools/fmt.rs
@@ -272,6 +272,7 @@ fn format_markdown(
| "njk"
| "yml"
| "yaml"
+ | "sql"
) {
// It's important to tell dprint proper file extension, otherwise
// it might parse the file twice.
@@ -301,6 +302,13 @@ fn format_markdown(
}
}
"yml" | "yaml" => format_yaml(text, fmt_options),
+ "sql" => {
+ if unstable_options.sql {
+ format_sql(text, fmt_options)
+ } else {
+ Ok(None)
+ }
+ }
_ => {
let mut codeblock_config =
get_resolved_typescript_config(fmt_options);
@@ -503,7 +511,48 @@ pub fn format_html(
})
}
-/// Formats a single TS, TSX, JS, JSX, JSONC, JSON, MD, or IPYNB file.
+pub fn format_sql(
+ file_text: &str,
+ fmt_options: &FmtOptionsConfig,
+) -> Result<Option<String>, AnyError> {
+ let ignore_file = file_text
+ .lines()
+ .take_while(|line| line.starts_with("--"))
+ .any(|line| {
+ line
+ .strip_prefix("--")
+ .unwrap()
+ .trim()
+ .starts_with("deno-fmt-ignore-file")
+ });
+
+ if ignore_file {
+ return Ok(None);
+ }
+
+ let mut formatted_str = sqlformat::format(
+ file_text,
+ &sqlformat::QueryParams::None,
+ &sqlformat::FormatOptions {
+ ignore_case_convert: None,
+ indent: if fmt_options.use_tabs.unwrap_or_default() {
+ sqlformat::Indent::Tabs
+ } else {
+ sqlformat::Indent::Spaces(fmt_options.indent_width.unwrap_or(2))
+ },
+ // leave one blank line between queries.
+ lines_between_queries: 2,
+ uppercase: Some(true),
+ },
+ );
+
+ // Add single new line to the end of file.
+ formatted_str.push('\n');
+
+ Ok(Some(formatted_str))
+}
+
+/// Formats a single TS, TSX, JS, JSX, JSONC, JSON, MD, IPYNB or SQL file.
pub fn format_file(
file_path: &Path,
file_text: &str,
@@ -538,6 +587,13 @@ pub fn format_file(
format_file(file_path, &file_text, fmt_options, unstable_options, None)
},
),
+ "sql" => {
+ if unstable_options.sql {
+ format_sql(file_text, fmt_options)
+ } else {
+ Ok(None)
+ }
+ }
_ => {
let config = get_resolved_typescript_config(fmt_options);
dprint_plugin_typescript::format_text(
@@ -1209,6 +1265,7 @@ fn is_supported_ext_fmt(path: &Path) -> bool {
| "yml"
| "yaml"
| "ipynb"
+ | "sql"
)
})
}
@@ -1269,6 +1326,11 @@ mod test {
assert!(is_supported_ext_fmt(Path::new("foo.yaml")));
assert!(is_supported_ext_fmt(Path::new("foo.YaML")));
assert!(is_supported_ext_fmt(Path::new("foo.ipynb")));
+ assert!(is_supported_ext_fmt(Path::new("foo.sql")));
+ assert!(is_supported_ext_fmt(Path::new("foo.Sql")));
+ assert!(is_supported_ext_fmt(Path::new("foo.sQl")));
+ assert!(is_supported_ext_fmt(Path::new("foo.sqL")));
+ assert!(is_supported_ext_fmt(Path::new("foo.SQL")));
}
#[test]
diff --git a/tests/integration/fmt_tests.rs b/tests/integration/fmt_tests.rs
index b890b3b72..ccf54a4d0 100644
--- a/tests/integration/fmt_tests.rs
+++ b/tests/integration/fmt_tests.rs
@@ -61,6 +61,12 @@ fn fmt_test() {
let badly_formatted_yaml = t.path().join("badly_formatted.yaml");
badly_formatted_original_yaml.copy(&badly_formatted_yaml);
+ let fixed_sql = testdata_fmt_dir.join("badly_formatted_fixed.sql");
+ let badly_formatted_original_sql =
+ testdata_fmt_dir.join("badly_formatted.sql");
+ let badly_formatted_sql = t.path().join("badly_formatted.sql");
+ badly_formatted_original_sql.copy(&badly_formatted_sql);
+
// First, check formatting by ignoring the badly formatted file.
let output = context
.new_command()
@@ -71,11 +77,12 @@ fn fmt_test() {
"--unstable-html".to_string(),
"--unstable-component".to_string(),
"--unstable-yaml".to_string(),
+ "--unstable-sql".to_string(),
format!(
- "--ignore={badly_formatted_js},{badly_formatted_md},{badly_formatted_json},{badly_formatted_css},{badly_formatted_html},{badly_formatted_component},{badly_formatted_yaml},{badly_formatted_ipynb}",
+ "--ignore={badly_formatted_js},{badly_formatted_md},{badly_formatted_json},{badly_formatted_css},{badly_formatted_html},{badly_formatted_component},{badly_formatted_yaml},{badly_formatted_ipynb},{badly_formatted_sql}",
),
format!(
- "--check {badly_formatted_js} {badly_formatted_md} {badly_formatted_json} {badly_formatted_css} {badly_formatted_html} {badly_formatted_component} {badly_formatted_yaml} {badly_formatted_ipynb}",
+ "--check {badly_formatted_js} {badly_formatted_md} {badly_formatted_json} {badly_formatted_css} {badly_formatted_html} {badly_formatted_component} {badly_formatted_yaml} {badly_formatted_ipynb} {badly_formatted_sql}",
),
])
.run();
@@ -95,6 +102,7 @@ fn fmt_test() {
"--unstable-html".to_string(),
"--unstable-component".to_string(),
"--unstable-yaml".to_string(),
+ "--unstable-sql".to_string(),
badly_formatted_js.to_string(),
badly_formatted_md.to_string(),
badly_formatted_json.to_string(),
@@ -103,6 +111,7 @@ fn fmt_test() {
badly_formatted_component.to_string(),
badly_formatted_yaml.to_string(),
badly_formatted_ipynb.to_string(),
+ badly_formatted_sql.to_string(),
])
.run();
@@ -119,6 +128,7 @@ fn fmt_test() {
"--unstable-html".to_string(),
"--unstable-component".to_string(),
"--unstable-yaml".to_string(),
+ "--unstable-sql".to_string(),
badly_formatted_js.to_string(),
badly_formatted_md.to_string(),
badly_formatted_json.to_string(),
@@ -127,6 +137,7 @@ fn fmt_test() {
badly_formatted_component.to_string(),
badly_formatted_yaml.to_string(),
badly_formatted_ipynb.to_string(),
+ badly_formatted_sql.to_string(),
])
.run();
@@ -141,6 +152,7 @@ fn fmt_test() {
let expected_component = fixed_component.read_to_string();
let expected_yaml = fixed_yaml.read_to_string();
let expected_ipynb = fixed_ipynb.read_to_string();
+ let expected_sql = fixed_sql.read_to_string();
let actual_js = badly_formatted_js.read_to_string();
let actual_md = badly_formatted_md.read_to_string();
let actual_json = badly_formatted_json.read_to_string();
@@ -149,6 +161,7 @@ fn fmt_test() {
let actual_component = badly_formatted_component.read_to_string();
let actual_yaml = badly_formatted_yaml.read_to_string();
let actual_ipynb = badly_formatted_ipynb.read_to_string();
+ let actual_sql = badly_formatted_sql.read_to_string();
assert_eq!(expected_js, actual_js);
assert_eq!(expected_md, actual_md);
assert_eq!(expected_json, actual_json);
@@ -157,6 +170,7 @@ fn fmt_test() {
assert_eq!(expected_component, actual_component);
assert_eq!(expected_yaml, actual_yaml);
assert_eq!(expected_ipynb, actual_ipynb);
+ assert_eq!(expected_sql, actual_sql);
}
#[test]
diff --git a/tests/specs/fmt/sql/__test__.jsonc b/tests/specs/fmt/sql/__test__.jsonc
new file mode 100644
index 000000000..a335e79c2
--- /dev/null
+++ b/tests/specs/fmt/sql/__test__.jsonc
@@ -0,0 +1,25 @@
+{
+ "tempDir": true,
+ "tests": {
+ "nothing": {
+ "args": "fmt",
+ "output": "Checked 7 files\n"
+ },
+ "flag": {
+ "args": "fmt --unstable-sql",
+ "output": "[UNORDERED_START]\n[WILDLINE]badly_formatted.sql\n[WILDLINE]well_formatted.sql\n[WILDLINE]wrong_file_ignore.sql\n[UNORDERED_END]\nChecked 7 files\n"
+ },
+ "config_file": {
+ "steps": [{
+ "args": [
+ "eval",
+ "Deno.writeTextFile('deno.json', '{\\n \"unstable\": [\"fmt-sql\"]\\n}\\n')"
+ ],
+ "output": "[WILDCARD]"
+ }, {
+ "args": "fmt",
+ "output": "[UNORDERED_START]\n[WILDLINE]badly_formatted.sql\n[WILDLINE]well_formatted.sql\n[WILDLINE]wrong_file_ignore.sql\n[UNORDERED_END]\nChecked 8 files\n"
+ }]
+ }
+ }
+}
diff --git a/tests/specs/fmt/sql/badly_formatted.sql b/tests/specs/fmt/sql/badly_formatted.sql
new file mode 100644
index 000000000..619fc7afd
--- /dev/null
+++ b/tests/specs/fmt/sql/badly_formatted.sql
@@ -0,0 +1 @@
+select *; \ No newline at end of file
diff --git a/tests/specs/fmt/sql/ignore_file.sql b/tests/specs/fmt/sql/ignore_file.sql
new file mode 100644
index 000000000..62418c611
--- /dev/null
+++ b/tests/specs/fmt/sql/ignore_file.sql
@@ -0,0 +1,3 @@
+-- deno-fmt-ignore-file
+
+foo%!
diff --git a/tests/specs/fmt/sql/ignore_file2.sql b/tests/specs/fmt/sql/ignore_file2.sql
new file mode 100644
index 000000000..fe9969f1d
--- /dev/null
+++ b/tests/specs/fmt/sql/ignore_file2.sql
@@ -0,0 +1,3 @@
+--deno-fmt-ignore-file
+
+foo%!
diff --git a/tests/specs/fmt/sql/ignore_file3.sql b/tests/specs/fmt/sql/ignore_file3.sql
new file mode 100644
index 000000000..c87da3e59
--- /dev/null
+++ b/tests/specs/fmt/sql/ignore_file3.sql
@@ -0,0 +1,6 @@
+-- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
+-- incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
+-- quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
+-- deno-fmt-ignore-file
+
+ foo%!
diff --git a/tests/specs/fmt/sql/ignore_file4.sql b/tests/specs/fmt/sql/ignore_file4.sql
new file mode 100644
index 000000000..2de65712a
--- /dev/null
+++ b/tests/specs/fmt/sql/ignore_file4.sql
@@ -0,0 +1,3 @@
+-- deno-fmt-ignore-file Foo bar biz
+
+ foo%!
diff --git a/tests/specs/fmt/sql/well_formatted.sql b/tests/specs/fmt/sql/well_formatted.sql
new file mode 100644
index 000000000..92ce98018
--- /dev/null
+++ b/tests/specs/fmt/sql/well_formatted.sql
@@ -0,0 +1,4 @@
+SELECT
+ *
+FROM
+ foo;
diff --git a/tests/specs/fmt/sql/wrong_file_ignore.sql b/tests/specs/fmt/sql/wrong_file_ignore.sql
new file mode 100644
index 000000000..c124855dc
--- /dev/null
+++ b/tests/specs/fmt/sql/wrong_file_ignore.sql
@@ -0,0 +1,6 @@
+-- File ignore directive only works if it's in the first cluster
+-- of comment, ie. there are no empty lines after the first n-leading lines.
+
+-- deno-fmt-ignore-file
+
+ foo \ No newline at end of file
diff --git a/tests/testdata/fmt/badly_formatted.md b/tests/testdata/fmt/badly_formatted.md
index 642918cea..be90ff845 100644
--- a/tests/testdata/fmt/badly_formatted.md
+++ b/tests/testdata/fmt/badly_formatted.md
@@ -63,3 +63,15 @@ function foo(): number {
let a:number
</script>
```
+
+
+```sql
+ seLect * , biz, buz
+from baz;
+```
+
+```sql
+-- deno-fmt-ignore-file
+ seLect * , biz, buz
+from baz;
+```
diff --git a/tests/testdata/fmt/badly_formatted.sql b/tests/testdata/fmt/badly_formatted.sql
new file mode 100644
index 000000000..8b4cb978f
--- /dev/null
+++ b/tests/testdata/fmt/badly_formatted.sql
@@ -0,0 +1,21 @@
+select * from foo;
+update foo set a = 'b'Where id = 'biz';
+
+
+ create table foo(id text not null
+bar text,
+ biz int,
+ buz number NOT NULL
+);
+
+INSERT
+ into
+ user_data
+ (first_name,
+last_name, address, phone, email)
+VALUES
+ ('foo', 'bar',
+ 'biz', 1, 'bix');
+
+
+
diff --git a/tests/testdata/fmt/badly_formatted_fixed.md b/tests/testdata/fmt/badly_formatted_fixed.md
index 21176742b..7a482e058 100644
--- a/tests/testdata/fmt/badly_formatted_fixed.md
+++ b/tests/testdata/fmt/badly_formatted_fixed.md
@@ -56,3 +56,18 @@ function foo(): number {
let a: number;
</script>
```
+
+```sql
+SELECT
+ *,
+ biz,
+ buz
+FROM
+ baz;
+```
+
+```sql
+-- deno-fmt-ignore-file
+ seLect * , biz, buz
+from baz;
+```
diff --git a/tests/testdata/fmt/badly_formatted_fixed.sql b/tests/testdata/fmt/badly_formatted_fixed.sql
new file mode 100644
index 000000000..d50c61921
--- /dev/null
+++ b/tests/testdata/fmt/badly_formatted_fixed.sql
@@ -0,0 +1,22 @@
+SELECT
+ *
+FROM
+ foo;
+
+UPDATE
+ foo
+SET
+ a = 'b'
+WHERE
+ id = 'biz';
+
+CREATE TABLE foo(
+ id text NOT NULL bar text,
+ biz int,
+ buz number NOT NULL
+);
+
+INSERT INTO
+ user_data (first_name, last_name, address, phone, email)
+VALUES
+ ('foo', 'bar', 'biz', 1, 'bix');