From 7c7262a122fb3bcd58acadfb3a43a759bdb793c3 Mon Sep 17 00:00:00 2001 From: Steve Dignam Date: Tue, 6 May 2025 22:33:41 -0400 Subject: [PATCH] update-readme --- README.md | 83 ++++++++++++------- .../src/rules/constraint_missing_not_valid.rs | 2 +- .../src/rules/disallow_unique_constraint.rs | 2 +- .../src/rules/prefer_identity.rs | 4 +- .../src/rules/prefer_text_field.rs | 2 +- .../require_concurrent_index_creation.rs | 4 +- ...id__test__adding_check_constraint_err.snap | 4 +- ...issing_not_valid__test__adding_fk_err.snap | 4 +- ...t__test__adding_unique_constraint_err.snap | 2 +- ...ique_constraint_inline_add_column_err.snap | 2 +- ...nstraint_inline_add_column_unique_err.snap | 2 +- ...er__rules__prefer_identity__test__err.snap | 24 +++--- ...eld__test__adding_column_non_text_err.snap | 2 +- ...eate_table_with_pgcatalog_varchar_err.snap | 2 +- ...__test__create_table_with_varchar_err.snap | 2 +- ...ield__test__increase_varchar_size_err.snap | 2 +- ...st__adding_index_non_concurrently_err.snap | 6 +- 17 files changed, 89 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index 9298c481..95f1c7e1 100644 --- a/README.md +++ b/README.md @@ -21,47 +21,70 @@ pip install squawk-cli https://github.com/sbdchd/squawk/releases ``` -### Without installation (Docker) +### Or via Docker -You can run Squawk without installation using Docker. The official image is available on GitHub Container Registry. +You can also run Squawk using Docker. The official image is available on GitHub Container Registry. ```shell # Assuming you want to check sql files in the current directory docker run --rm -v $(pwd):/data ghcr.io/sbdchd/squawk:latest *.sql ``` -## Usage - -```shell -❯ squawk example.sql -example.sql:2:1: warning: prefer-text-field - - 2 | -- - 3 | -- Create model Bar - 4 | -- - 5 | CREATE TABLE "core_bar" ( - 6 | "id" serial NOT NULL PRIMARY KEY, - 7 | "alpha" varchar(100) NOT NULL - 8 | ); - - note: Changing the size of a varchar field requires an ACCESS EXCLUSIVE lock. - help: Use a text field with a check constraint. +### Or via the Playground -example.sql:9:2: warning: require-concurrent-index-creation +Use the WASM powered playground to check your SQL locally in the browser! - 9 | - 10 | CREATE INDEX "field_name_idx" ON "table_name" ("field_name"); + - note: Creating an index blocks writes. - note: Create the index CONCURRENTLY. - -example.sql:11:2: warning: disallowed-unique-constraint - - 11 | - 12 | ALTER TABLE table_name ADD CONSTRAINT field_name_constraint UNIQUE (field_name); +## Usage - note: Adding a UNIQUE constraint requires an ACCESS EXCLUSIVE lock which blocks reads. - help: Create an index CONCURRENTLY and create the constraint using the index. +```shell +❯ squawk example.sql +warning[prefer-bigint-over-int]: Using 32-bit integer fields can result in hitting the max `int` limit. + --> example.sql:6:10 + | +6 | "id" serial NOT NULL PRIMARY KEY, + | ^^^^^^ + | + = help: Use 64-bit integer values instead to prevent hitting this limit. +warning[prefer-identity]: Serial types make schema, dependency, and permission management difficult. + --> example.sql:6:10 + | +6 | "id" serial NOT NULL PRIMARY KEY, + | ^^^^^^ + | + = help: Use Identity columns instead. +warning[prefer-text-field]: Changing the size of a `varchar` field requires an `ACCESS EXCLUSIVE` lock, that will prevent all reads and writes to the table. + --> example.sql:7:13 + | +7 | "alpha" varchar(100) NOT NULL + | ^^^^^^^^^^^^ + | + = help: Use a `TEXT` field with a `CHECK` constraint. +warning[require-concurrent-index-creation]: During normal index creation, table updates are blocked, but reads are still allowed. + --> example.sql:10:1 + | +10 | CREATE INDEX "field_name_idx" ON "table_name" ("field_name"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: Use `CONCURRENTLY` to avoid blocking writes. +warning[constraint-missing-not-valid]: By default new constraints require a table scan and block writes to the table while that scan occurs. + --> example.sql:12:24 + | +12 | ALTER TABLE table_name ADD CONSTRAINT field_name_constraint UNIQUE (field_name); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: Use `NOT VALID` with a later `VALIDATE CONSTRAINT` call. +warning[disallowed-unique-constraint]: Adding a `UNIQUE` constraint requires an `ACCESS EXCLUSIVE` lock which blocks reads and writes to the table while the index is built. + --> example.sql:12:28 + | +12 | ALTER TABLE table_name ADD CONSTRAINT field_name_constraint UNIQUE (field_name); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: Create an index `CONCURRENTLY` and create the constraint using the index. + +Find detailed examples and solutions for each rule at https://squawkhq.com/docs/rules +Found 7 issues in 1 file (checked 1 source file) ``` ### `squawk --help` diff --git a/crates/squawk_linter/src/rules/constraint_missing_not_valid.rs b/crates/squawk_linter/src/rules/constraint_missing_not_valid.rs index bfc49f74..c3a915c3 100644 --- a/crates/squawk_linter/src/rules/constraint_missing_not_valid.rs +++ b/crates/squawk_linter/src/rules/constraint_missing_not_valid.rs @@ -131,7 +131,7 @@ pub(crate) fn constraint_missing_not_valid(ctx: &mut Linter, parse: &Parse) { let message = "Adding a `UNIQUE` constraint requires an `ACCESS EXCLUSIVE` lock which blocks reads and writes to the table while the index is built."; - let help = "Create an index CONCURRENTLY and create the constraint using the index."; + let help = "Create an index `CONCURRENTLY` and create the constraint using the index."; let file = parse.tree(); let tables_created = tables_created_in_transaction(ctx.settings.assume_in_transaction, &file); for item in file.items() { diff --git a/crates/squawk_linter/src/rules/prefer_identity.rs b/crates/squawk_linter/src/rules/prefer_identity.rs index 2395ead8..51cf42f8 100644 --- a/crates/squawk_linter/src/rules/prefer_identity.rs +++ b/crates/squawk_linter/src/rules/prefer_identity.rs @@ -27,9 +27,9 @@ fn check_ty_for_serial(ctx: &mut Linter, ty: Option) { if is_not_valid_int_type(&ty, &SERIAL_TYPES) { ctx.report(Violation::new( Rule::PreferIdentity, - "Serial types make schema, dependency, and permission management difficult. Use Identity columns instead.".into(), + "Serial types make schema, dependency, and permission management difficult.".into(), ty.syntax().text_range(), - "Use Identity columns instead.".to_string(), + "Use an `IDENTITY` column instead.".to_string(), )); }; } diff --git a/crates/squawk_linter/src/rules/prefer_text_field.rs b/crates/squawk_linter/src/rules/prefer_text_field.rs index 122e2032..97637312 100644 --- a/crates/squawk_linter/src/rules/prefer_text_field.rs +++ b/crates/squawk_linter/src/rules/prefer_text_field.rs @@ -54,7 +54,7 @@ fn check_ty_for_varchar(ctx: &mut Linter, ty: Option) { Rule::PreferTextField, "Changing the size of a `varchar` field requires an `ACCESS EXCLUSIVE` lock, that will prevent all reads and writes to the table.".to_string(), ty.syntax().text_range(), - "Use a `text` field with a `check` constraint.".to_string(), + "Use a `TEXT` field with a `CHECK` constraint.".to_string(), )); }; } diff --git a/crates/squawk_linter/src/rules/require_concurrent_index_creation.rs b/crates/squawk_linter/src/rules/require_concurrent_index_creation.rs index 0daf1865..f364b7ce 100644 --- a/crates/squawk_linter/src/rules/require_concurrent_index_creation.rs +++ b/crates/squawk_linter/src/rules/require_concurrent_index_creation.rs @@ -22,9 +22,9 @@ pub(crate) fn require_concurrent_index_creation(ctx: &mut Linter, parse: &Parse< { ctx.report(Violation::new( Rule::RequireConcurrentIndexCreation, - "During a normal index creation, table updates are blocked, but reads are still allowed. `CONCURRENTLY` avoids locking the table against writes during index creation.".into(), + "During normal index creation, table updates are blocked, but reads are still allowed.".into(), create_index.syntax().text_range(), - None, + "Use `CONCURRENTLY` to avoid blocking writes.".to_string(), )); } } diff --git a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__constraint_missing_not_valid__test__adding_check_constraint_err.snap b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__constraint_missing_not_valid__test__adding_check_constraint_err.snap index e4ecb32a..0dfffea9 100644 --- a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__constraint_missing_not_valid__test__adding_check_constraint_err.snap +++ b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__constraint_missing_not_valid__test__adding_check_constraint_err.snap @@ -7,6 +7,8 @@ expression: errors code: ConstraintMissingNotValid, message: "By default new constraints require a table scan and block writes to the table while that scan occurs.", text_range: 38..94, - help: None, + help: Some( + "Use `NOT VALID` with a later `VALIDATE CONSTRAINT` call.", + ), }, ] diff --git a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__constraint_missing_not_valid__test__adding_fk_err.snap b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__constraint_missing_not_valid__test__adding_fk_err.snap index 70418553..3b46cd10 100644 --- a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__constraint_missing_not_valid__test__adding_fk_err.snap +++ b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__constraint_missing_not_valid__test__adding_fk_err.snap @@ -7,6 +7,8 @@ expression: errors code: ConstraintMissingNotValid, message: "By default new constraints require a table scan and block writes to the table while that scan occurs.", text_range: 40..114, - help: None, + help: Some( + "Use `NOT VALID` with a later `VALIDATE CONSTRAINT` call.", + ), }, ] diff --git a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__disallow_unique_constraint__test__adding_unique_constraint_err.snap b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__disallow_unique_constraint__test__adding_unique_constraint_err.snap index da344db7..072c18e4 100644 --- a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__disallow_unique_constraint__test__adding_unique_constraint_err.snap +++ b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__disallow_unique_constraint__test__adding_unique_constraint_err.snap @@ -8,7 +8,7 @@ expression: errors message: "Adding a `UNIQUE` constraint requires an `ACCESS EXCLUSIVE` lock which blocks reads and writes to the table while the index is built.", text_range: 28..80, help: Some( - "Create an index CONCURRENTLY and create the constraint using the index.", + "Create an index `CONCURRENTLY` and create the constraint using the index.", ), }, ] diff --git a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__disallow_unique_constraint__test__unique_constraint_inline_add_column_err.snap b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__disallow_unique_constraint__test__unique_constraint_inline_add_column_err.snap index f1dd4873..479ba3cf 100644 --- a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__disallow_unique_constraint__test__unique_constraint_inline_add_column_err.snap +++ b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__disallow_unique_constraint__test__unique_constraint_inline_add_column_err.snap @@ -8,7 +8,7 @@ expression: errors message: "Adding a `UNIQUE` constraint requires an `ACCESS EXCLUSIVE` lock which blocks reads and writes to the table while the index is built.", text_range: 37..69, help: Some( - "Create an index CONCURRENTLY and create the constraint using the index.", + "Create an index `CONCURRENTLY` and create the constraint using the index.", ), }, ] diff --git a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__disallow_unique_constraint__test__unique_constraint_inline_add_column_unique_err.snap b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__disallow_unique_constraint__test__unique_constraint_inline_add_column_unique_err.snap index 0acc94e3..b0f88051 100644 --- a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__disallow_unique_constraint__test__unique_constraint_inline_add_column_unique_err.snap +++ b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__disallow_unique_constraint__test__unique_constraint_inline_add_column_unique_err.snap @@ -8,7 +8,7 @@ expression: errors message: "Adding a `UNIQUE` constraint requires an `ACCESS EXCLUSIVE` lock which blocks reads and writes to the table while the index is built.", text_range: 37..43, help: Some( - "Create an index CONCURRENTLY and create the constraint using the index.", + "Create an index `CONCURRENTLY` and create the constraint using the index.", ), }, ] diff --git a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_identity__test__err.snap b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_identity__test__err.snap index db10e813..5b2490c9 100644 --- a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_identity__test__err.snap +++ b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_identity__test__err.snap @@ -5,50 +5,50 @@ expression: errors [ Violation { code: PreferIdentity, - message: "Serial types make schema, dependency, and permission management difficult. Use Identity columns instead.", + message: "Serial types make schema, dependency, and permission management difficult.", text_range: 29..35, help: Some( - "Use Identity columns instead.", + "Use an `IDENTITY` column instead.", ), }, Violation { code: PreferIdentity, - message: "Serial types make schema, dependency, and permission management difficult. Use Identity columns instead.", + message: "Serial types make schema, dependency, and permission management difficult.", text_range: 67..74, help: Some( - "Use Identity columns instead.", + "Use an `IDENTITY` column instead.", ), }, Violation { code: PreferIdentity, - message: "Serial types make schema, dependency, and permission management difficult. Use Identity columns instead.", + message: "Serial types make schema, dependency, and permission management difficult.", text_range: 106..113, help: Some( - "Use Identity columns instead.", + "Use an `IDENTITY` column instead.", ), }, Violation { code: PreferIdentity, - message: "Serial types make schema, dependency, and permission management difficult. Use Identity columns instead.", + message: "Serial types make schema, dependency, and permission management difficult.", text_range: 145..152, help: Some( - "Use Identity columns instead.", + "Use an `IDENTITY` column instead.", ), }, Violation { code: PreferIdentity, - message: "Serial types make schema, dependency, and permission management difficult. Use Identity columns instead.", + message: "Serial types make schema, dependency, and permission management difficult.", text_range: 184..195, help: Some( - "Use Identity columns instead.", + "Use an `IDENTITY` column instead.", ), }, Violation { code: PreferIdentity, - message: "Serial types make schema, dependency, and permission management difficult. Use Identity columns instead.", + message: "Serial types make schema, dependency, and permission management difficult.", text_range: 227..236, help: Some( - "Use Identity columns instead.", + "Use an `IDENTITY` column instead.", ), }, ] diff --git a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_text_field__test__adding_column_non_text_err.snap b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_text_field__test__adding_column_non_text_err.snap index c83f24a4..c3c077cf 100644 --- a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_text_field__test__adding_column_non_text_err.snap +++ b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_text_field__test__adding_column_non_text_err.snap @@ -8,7 +8,7 @@ expression: errors message: "Changing the size of a `varchar` field requires an `ACCESS EXCLUSIVE` lock, that will prevent all reads and writes to the table.", text_range: 56..68, help: Some( - "Use a `text` field with a `check` constraint.", + "Use a `TEXT` field with a `CHECK` constraint.", ), }, ] diff --git a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_text_field__test__create_table_with_pgcatalog_varchar_err.snap b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_text_field__test__create_table_with_pgcatalog_varchar_err.snap index 6192597f..e4ee461a 100644 --- a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_text_field__test__create_table_with_pgcatalog_varchar_err.snap +++ b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_text_field__test__create_table_with_pgcatalog_varchar_err.snap @@ -8,7 +8,7 @@ expression: errors message: "Changing the size of a `varchar` field requires an `ACCESS EXCLUSIVE` lock, that will prevent all reads and writes to the table.", text_range: 69..92, help: Some( - "Use a `text` field with a `check` constraint.", + "Use a `TEXT` field with a `CHECK` constraint.", ), }, ] diff --git a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_text_field__test__create_table_with_varchar_err.snap b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_text_field__test__create_table_with_varchar_err.snap index 5f2f3052..9bbdef6a 100644 --- a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_text_field__test__create_table_with_varchar_err.snap +++ b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_text_field__test__create_table_with_varchar_err.snap @@ -8,7 +8,7 @@ expression: errors message: "Changing the size of a `varchar` field requires an `ACCESS EXCLUSIVE` lock, that will prevent all reads and writes to the table.", text_range: 111..123, help: Some( - "Use a `text` field with a `check` constraint.", + "Use a `TEXT` field with a `CHECK` constraint.", ), }, ] diff --git a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_text_field__test__increase_varchar_size_err.snap b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_text_field__test__increase_varchar_size_err.snap index 7578baad..2b792804 100644 --- a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_text_field__test__increase_varchar_size_err.snap +++ b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_text_field__test__increase_varchar_size_err.snap @@ -8,7 +8,7 @@ expression: errors message: "Changing the size of a `varchar` field requires an `ACCESS EXCLUSIVE` lock, that will prevent all reads and writes to the table.", text_range: 89..102, help: Some( - "Use a `text` field with a `check` constraint.", + "Use a `TEXT` field with a `CHECK` constraint.", ), }, ] diff --git a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__require_concurrent_index_creation__test__adding_index_non_concurrently_err.snap b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__require_concurrent_index_creation__test__adding_index_non_concurrently_err.snap index 316e678f..ea881b2f 100644 --- a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__require_concurrent_index_creation__test__adding_index_non_concurrently_err.snap +++ b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__require_concurrent_index_creation__test__adding_index_non_concurrently_err.snap @@ -5,8 +5,10 @@ expression: errors [ Violation { code: RequireConcurrentIndexCreation, - message: "During a normal index creation, table updates are blocked, but reads are still allowed. `CONCURRENTLY` avoids locking the table against writes during index creation.", + message: "During normal index creation, table updates are blocked, but reads are still allowed.", text_range: 15..75, - help: None, + help: Some( + "Use `CONCURRENTLY` to avoid blocking writes.", + ), }, ]