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
83 changes: 53 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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");
<https://play.squawkhq.com>

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`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ pub(crate) fn constraint_missing_not_valid(ctx: &mut Linter, parse: &Parse<Sourc
Rule::ConstraintMissingNotValid,
"By default new constraints require a table scan and block writes to the table while that scan occurs.".into(),
add_constraint.syntax().text_range(),
None,
"Use `NOT VALID` with a later `VALIDATE CONSTRAINT` call.".to_string(),
));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use super::constraint_missing_not_valid::tables_created_in_transaction;

pub(crate) fn disallow_unique_constraint(ctx: &mut Linter, parse: &Parse<SourceFile>) {
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() {
Expand Down
4 changes: 2 additions & 2 deletions crates/squawk_linter/src/rules/prefer_identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ fn check_ty_for_serial(ctx: &mut Linter, ty: Option<ast::Type>) {
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(),
));
};
}
Expand Down
2 changes: 1 addition & 1 deletion crates/squawk_linter/src/rules/prefer_text_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ fn check_ty_for_varchar(ctx: &mut Linter, ty: Option<ast::Type>) {
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(),
));
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
),
},
]
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
),
},
]
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
),
},
]
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
),
},
]
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
),
},
]
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
),
},
]
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
),
},
]
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
),
},
]
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
),
},
]
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
),
},
]
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
),
},
]
Loading