Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 16 additions & 15 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,11 @@ smol_str = "0.3.2"
enum-iterator = "2.1.0"
jiff = "0.2.24"
itertools = "0.14.0"
line-index = "0.1.2"
lsp-server = "0.7.8"
memchr = "2.8.0"
text-size = "1.1.1"
nohash-hasher = "0.2.0"
oorandom = "11.1.5"
gen-lsp-types = { version = "0.11", features = ["url"] }
serde-wasm-bindgen = "0.6.5"
wasm-bindgen = "0.2.114"
Expand Down Expand Up @@ -83,6 +86,7 @@ rustc-hash = "2.1.1"
squawk-github = { path = "./crates/squawk_github", version = "2.61.0" }
squawk-ide = { path = "./crates/squawk_ide", version = "2.61.0" }
squawk-lexer = { path = "./crates/squawk_lexer", version = "2.61.0" }
squawk-line-index = { path = "./crates/squawk_line_index", version = "2.61.0" }
squawk-parser = { path = "./crates/squawk_parser", version = "2.61.0" }
squawk-syntax = { path = "./crates/squawk_syntax", version = "2.61.0" }
squawk-linter = { path = "./crates/squawk_linter", version = "2.61.0" }
Expand All @@ -108,4 +112,5 @@ insta.opt-level = 3
similar.opt-level = 3
# These speed up local tests.
rowan.opt-level = 3
squawk-line-index.opt-level = 3
text-size.opt-level = 3
2 changes: 1 addition & 1 deletion crates/squawk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ glob.workspace = true
rayon.workspace = true
anyhow.workspace = true
annotate-snippets.workspace = true
line-index.workspace = true
squawk-line-index.workspace = true
lsp-server.workspace = true

[dev-dependencies]
Expand Down
2 changes: 1 addition & 1 deletion crates/squawk/src/github.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ mod test_github_comment {
};

use insta::assert_snapshot;
use line_index::{TextRange, TextSize};
use squawk_line_index::{TextRange, TextSize};

/// Most cases, hopefully, will be a single migration for a given PR, but
/// let's check the case of multiple migrations
Expand Down
2 changes: 1 addition & 1 deletion crates/squawk/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ pub enum DebugOption {
Ast,
}

#[derive(Debug, ValueEnum, Clone, Default)]
#[derive(Debug, ValueEnum, Clone, Copy, Default)]
pub enum Reporter {
#[default]
Tty,
Expand Down
84 changes: 82 additions & 2 deletions crates/squawk/src/reporter.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use annotate_snippets::{AnnotationKind, Level, Patch, Renderer, Snippet, renderer::DecorStyle};
use anyhow::Result;
use console::style;
use line_index::LineIndex;
use line_index::TextRange;
use log::info;
use rayon::prelude::*;
use serde::Serialize;
use squawk_line_index::LineIndex;
use squawk_line_index::TextRange;
use squawk_linter::{Fix, Linter, Rule, Version};
use squawk_syntax::SourceFile;
use std::hash::DefaultHasher;
Expand Down Expand Up @@ -672,4 +672,84 @@ SELECT 1;
let filename = "main.sql";
assert_debug_snapshot!(check_sql(sql, filename, &[], &[], None, false));
}

fn sql_with_line_ending(line_ending: &str) -> String {
[
r#"ALTER TABLE "core_recipe" ADD COLUMN "foo" integer NOT NULL;"#,
r#"ALTER TABLE "core_foo" ADD COLUMN "bar" integer NOT NULL;"#,
"SELECT 1;",
"",
]
.join(line_ending)
}

fn report(sql: &str, reporter: Reporter) -> String {
let mut buff = Vec::new();
print_violations(
&mut buff,
vec![check_sql(sql, "main.sql", &[], &[], None, false)],
&reporter,
false,
)
.unwrap();
// make the carriage returns visible instead of mangling the snapshot
strip_ansi_codes(&String::from_utf8_lossy(&buff)).replace('\r', "<CR>")
}

#[test]
fn line_endings_lf_gcc() {
assert_snapshot!(report(&sql_with_line_ending("\n"), Reporter::Gcc), @"
main.sql:0:0: warning: require-lock-timeout Missing `set lock_timeout` before potentially slow ACCESS EXCLUSIVE lock operations
main.sql:0:0: warning: require-statement-timeout Missing `set statement_timeout` before potentially slow operations
main.sql:0:26: warning: adding-required-field Adding a new column that is `NOT NULL` and has no default value to an existing table effectively makes it required.
main.sql:0:26: warning: prefer-robust-stmts Missing `IF NOT EXISTS`, the migration can't be rerun if it fails part way through.
main.sql:0:43: warning: prefer-bigint-over-int Using 32-bit integer fields can result in hitting the max `int` limit.
main.sql:1:23: warning: adding-required-field Adding a new column that is `NOT NULL` and has no default value to an existing table effectively makes it required.
main.sql:1:23: warning: prefer-robust-stmts Missing `IF NOT EXISTS`, the migration can't be rerun if it fails part way through.
main.sql:1:40: warning: prefer-bigint-over-int Using 32-bit integer fields can result in hitting the max `int` limit.
");
}

#[test]
fn line_endings_crlf_gcc() {
assert_snapshot!(report(&sql_with_line_ending("\r\n"), Reporter::Gcc), @"
main.sql:0:0: warning: require-lock-timeout Missing `set lock_timeout` before potentially slow ACCESS EXCLUSIVE lock operations
main.sql:0:0: warning: require-statement-timeout Missing `set statement_timeout` before potentially slow operations
main.sql:0:26: warning: adding-required-field Adding a new column that is `NOT NULL` and has no default value to an existing table effectively makes it required.
main.sql:0:26: warning: prefer-robust-stmts Missing `IF NOT EXISTS`, the migration can't be rerun if it fails part way through.
main.sql:0:43: warning: prefer-bigint-over-int Using 32-bit integer fields can result in hitting the max `int` limit.
main.sql:1:23: warning: adding-required-field Adding a new column that is `NOT NULL` and has no default value to an existing table effectively makes it required.
main.sql:1:23: warning: prefer-robust-stmts Missing `IF NOT EXISTS`, the migration can't be rerun if it fails part way through.
main.sql:1:40: warning: prefer-bigint-over-int Using 32-bit integer fields can result in hitting the max `int` limit.
");
}

#[test]
fn line_endings_cr_gcc() {
assert_snapshot!(report(&sql_with_line_ending("\r"), Reporter::Gcc), @"
main.sql:0:0: warning: require-lock-timeout Missing `set lock_timeout` before potentially slow ACCESS EXCLUSIVE lock operations
main.sql:0:0: warning: require-statement-timeout Missing `set statement_timeout` before potentially slow operations
main.sql:0:26: warning: adding-required-field Adding a new column that is `NOT NULL` and has no default value to an existing table effectively makes it required.
main.sql:0:26: warning: prefer-robust-stmts Missing `IF NOT EXISTS`, the migration can't be rerun if it fails part way through.
main.sql:0:43: warning: prefer-bigint-over-int Using 32-bit integer fields can result in hitting the max `int` limit.
main.sql:1:23: warning: adding-required-field Adding a new column that is `NOT NULL` and has no default value to an existing table effectively makes it required.
main.sql:1:23: warning: prefer-robust-stmts Missing `IF NOT EXISTS`, the migration can't be rerun if it fails part way through.
main.sql:1:40: warning: prefer-bigint-over-int Using 32-bit integer fields can result in hitting the max `int` limit.
");
}

#[test]
fn line_endings_lf_tty() {
assert_snapshot!(report(&sql_with_line_ending("\n"), Reporter::Tty));
}

#[test]
fn line_endings_crlf_tty() {
assert_snapshot!(report(&sql_with_line_ending("\r\n"), Reporter::Tty));
}

#[test]
fn line_endings_cr_tty() {
assert_snapshot!(report(&sql_with_line_ending("\r"), Reporter::Tty));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
source: crates/squawk/src/reporter.rs
expression: "report(&sql_with_line_ending(\"\\r\"), Reporter::Tty)"
---
warning[]8;;https://squawkhq.com/docs/require-lock-timeout\require-lock-timeout]8;;\]: Missing `set lock_timeout` before potentially slow ACCESS EXCLUSIVE lock operations
╭▸ main.sql:1:1
1 │ ALTER TABLE "core_recipe" ADD COLUMN "foo" integer NOT NULL;␍ALTER TABLE "core_foo" ADD COLUMN "bar" integer NOT NULL;␍SELECT 1;␍
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
├ help: Configure a `lock_timeout` before this statement. Statement requires: ACCESS EXCLUSIVE lock; blocking: reads, writes, schema changes.
╭╴
1 + set lock_timeout = '1s';
╰╴
warning[]8;;https://squawkhq.com/docs/require-statement-timeout\require-statement-timeout]8;;\]: Missing `set statement_timeout` before potentially slow operations
╭▸ main.sql:1:1
1 │ ALTER TABLE "core_recipe" ADD COLUMN "foo" integer NOT NULL;␍ALTER TABLE "core_foo" ADD COLUMN "bar" integer NOT NULL;␍SELECT 1;␍
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
├ help: Configure a `statement_timeout` before this statement
╭╴
1 + set statement_timeout = '5s';
╰╴
warning[]8;;https://squawkhq.com/docs/adding-required-field\adding-required-field]8;;\]: Adding a new column that is `NOT NULL` and has no default value to an existing table effectively makes it required.
╭▸ main.sql:1:27
1 │ ALTER TABLE "core_recipe" ADD COLUMN "foo" integer NOT NULL;␍ALTER TABLE "core_foo" ADD COLUMN "bar" integer NOT NULL;␍SELECT 1;␍
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
╰ help: Make the field nullable or add a non-VOLATILE DEFAULT
warning[]8;;https://squawkhq.com/docs/prefer-robust-stmts\prefer-robust-stmts]8;;\]: Missing `IF NOT EXISTS`, the migration can't be rerun if it fails part way through.
╭▸ main.sql:1:27
1 │ ALTER TABLE "core_recipe" ADD COLUMN "foo" integer NOT NULL;␍ALTER TABLE "core_foo" ADD COLUMN "bar" integer NOT NULL;␍SELECT 1;␍
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
╭╴
1 │ ALTER TABLE "core_recipe" ADD COLUMN if not exists "foo" integer NOT NULL;␍ALTER TABLE "core_foo" ADD COLUMN "bar" integer NOT NULL;␍SELECT 1;␍
╰╴ +++++++++++++
warning[]8;;https://squawkhq.com/docs/prefer-bigint-over-int\prefer-bigint-over-int]8;;\]: Using 32-bit integer fields can result in hitting the max `int` limit.
╭▸ main.sql:1:44
1 │ ALTER TABLE "core_recipe" ADD COLUMN "foo" integer NOT NULL;␍ALTER TABLE "core_foo" ADD COLUMN "bar" integer NOT NULL;␍SELECT 1;␍
│ ━━━━━━━
├ help: Use 64-bit integer values instead to prevent hitting this limit.
╭╴
1 - ALTER TABLE "core_recipe" ADD COLUMN "foo" integer NOT NULL;␍ALTER TABLE "core_foo" ADD COLUMN "bar" integer NOT NULL;␍SELECT 1;␍
1 + ALTER TABLE "core_recipe" ADD COLUMN "foo" bigint NOT NULL;␍ALTER TABLE "core_foo" ADD COLUMN "bar" integer NOT NULL;␍SELECT 1;␍
╰╴
warning[]8;;https://squawkhq.com/docs/adding-required-field\adding-required-field]8;;\]: Adding a new column that is `NOT NULL` and has no default value to an existing table effectively makes it required.
╭▸ main.sql:1:85
1 │ ALTER TABLE "core_recipe" ADD COLUMN "foo" integer NOT NULL;␍ALTER TABLE "core_foo" ADD COLUMN "bar" integer NOT NULL;␍SELECT 1;␍
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
╰ help: Make the field nullable or add a non-VOLATILE DEFAULT
warning[]8;;https://squawkhq.com/docs/prefer-robust-stmts\prefer-robust-stmts]8;;\]: Missing `IF NOT EXISTS`, the migration can't be rerun if it fails part way through.
╭▸ main.sql:1:85
1 │ ALTER TABLE "core_recipe" ADD COLUMN "foo" integer NOT NULL;␍ALTER TABLE "core_foo" ADD COLUMN "bar" integer NOT NULL;␍SELECT 1;␍
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
╭╴
1 │ ALTER TABLE "core_recipe" ADD COLUMN "foo" integer NOT NULL;␍ALTER TABLE "core_foo" ADD COLUMN if not exists "bar" integer NOT NULL;␍SELECT 1;␍
╰╴ +++++++++++++
warning[]8;;https://squawkhq.com/docs/prefer-bigint-over-int\prefer-bigint-over-int]8;;\]: Using 32-bit integer fields can result in hitting the max `int` limit.
╭▸ main.sql:1:102
1 │ ALTER TABLE "core_recipe" ADD COLUMN "foo" integer NOT NULL;␍ALTER TABLE "core_foo" ADD COLUMN "bar" integer NOT NULL;␍SELECT 1;␍
│ ━━━━━━━
├ help: Use 64-bit integer values instead to prevent hitting this limit.
╭╴
1 - ALTER TABLE "core_recipe" ADD COLUMN "foo" integer NOT NULL;␍ALTER TABLE "core_foo" ADD COLUMN "bar" integer NOT NULL;␍SELECT 1;␍
1 + ALTER TABLE "core_recipe" ADD COLUMN "foo" integer NOT NULL;␍ALTER TABLE "core_foo" ADD COLUMN "bar" bigint NOT NULL;␍SELECT 1;␍
╰╴

Find detailed examples and solutions for each rule at https://squawkhq.com/docs/rules
Found 8 issues in 1 file (checked 1 source file)
Loading
Loading