Skip to content

Commit fdb6bc9

Browse files
authored
linter: fixes for prefer-text-field (#621)
1 parent d1604fc commit fdb6bc9

5 files changed

+124
-9
lines changed

crates/squawk_linter/src/rules/prefer_text_field.rs

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use squawk_syntax::{
55
ast::{self, AstNode},
66
};
77

8-
use crate::{Linter, Rule, Violation, identifier::Identifier};
8+
use crate::{Edit, Fix, Linter, Rule, Violation, identifier::Identifier};
99

1010
use crate::visitors::check_not_allowed_types;
1111

@@ -49,14 +49,38 @@ fn is_not_allowed_varchar(ty: &ast::Type) -> bool {
4949
}
5050
}
5151

52+
fn create_varchar_to_text_fix(ty: &ast::Type) -> Option<Fix> {
53+
match ty {
54+
ast::Type::PathType(path_type) => {
55+
// we'll replace the entire path type, including args
56+
// so: `"varchar"(100)` becomes `text`
57+
let edit = Edit::replace(path_type.syntax().text_range(), "text");
58+
Some(Fix::new("Replace with `text`", vec![edit]))
59+
}
60+
ast::Type::CharType(char_type) => {
61+
// we'll replace the entire char type, including args
62+
// so: `varchar(100)` becomes `text`
63+
let edit = Edit::replace(char_type.syntax().text_range(), "text");
64+
Some(Fix::new("Replace with `text`", vec![edit]))
65+
}
66+
ast::Type::ArrayType(array_type) => {
67+
let ty = array_type.ty()?;
68+
let edit = Edit::replace(ty.syntax().text_range(), "text");
69+
Some(Fix::new("Replace with `text`", vec![edit]))
70+
}
71+
_ => None,
72+
}
73+
}
74+
5275
fn check_ty_for_varchar(ctx: &mut Linter, ty: Option<ast::Type>) {
5376
if let Some(ty) = ty {
5477
if is_not_allowed_varchar(&ty) {
78+
let fix = create_varchar_to_text_fix(&ty);
5579
ctx.report(Violation::for_node(
5680
Rule::PreferTextField,
5781
"Changing the size of a `varchar` field requires an `ACCESS EXCLUSIVE` lock, that will prevent all reads and writes to the table.".to_string(),
5882
ty.syntax(),
59-
).help("Use a `TEXT` field with a `CHECK` constraint."));
83+
).help("Use a `TEXT` field with a `CHECK` constraint.").fix(fix));
6084
};
6185
}
6286
}
@@ -68,10 +92,16 @@ pub(crate) fn prefer_text_field(ctx: &mut Linter, parse: &Parse<SourceFile>) {
6892

6993
#[cfg(test)]
7094
mod test {
71-
use insta::assert_debug_snapshot;
95+
use insta::{assert_debug_snapshot, assert_snapshot};
7296

73-
use crate::Rule;
74-
use crate::test_utils::lint;
97+
use crate::{
98+
Rule,
99+
test_utils::{fix_sql, lint},
100+
};
101+
102+
fn fix(sql: &str) -> String {
103+
fix_sql(sql, Rule::PreferTextField)
104+
}
75105

76106
/// Changing a column of varchar(255) to varchar(1000) requires an ACCESS
77107
/// EXCLUSIVE lock
@@ -162,4 +192,41 @@ COMMIT;
162192
let errors = lint(sql, Rule::PreferTextField);
163193
assert_eq!(errors.len(), 0);
164194
}
195+
196+
#[test]
197+
fn fix_varchar_with_length() {
198+
assert_snapshot!(fix("CREATE TABLE t (c varchar(100));"), @"CREATE TABLE t (c text);");
199+
assert_snapshot!(fix("CREATE TABLE t (c varchar(255));"), @"CREATE TABLE t (c text);");
200+
assert_snapshot!(fix("CREATE TABLE t (c varchar(50));"), @"CREATE TABLE t (c text);");
201+
}
202+
203+
#[test]
204+
fn fix_mixed_case_varchar() {
205+
assert_snapshot!(fix("CREATE TABLE t (c VARCHAR(100));"), @"CREATE TABLE t (c text);");
206+
assert_snapshot!(fix("CREATE TABLE t (c Varchar(50));"), @"CREATE TABLE t (c text);");
207+
assert_snapshot!(fix("CREATE TABLE t (c VarChar(255));"), @"CREATE TABLE t (c text);");
208+
}
209+
210+
#[test]
211+
fn fix_varchar_arrays() {
212+
assert_snapshot!(fix("CREATE TABLE t (c varchar(100)[]);"), @"CREATE TABLE t (c text[]);");
213+
assert_snapshot!(fix("CREATE TABLE t (c varchar(255)[5]);"), @"CREATE TABLE t (c text[5]);");
214+
assert_snapshot!(fix("CREATE TABLE t (c varchar(50)[3][4]);"), @"CREATE TABLE t (c text[3][4]);");
215+
}
216+
217+
#[test]
218+
fn fix_alter_table() {
219+
assert_snapshot!(fix("ALTER TABLE t ADD COLUMN c varchar(100);"), @"ALTER TABLE t ADD COLUMN c text;");
220+
assert_snapshot!(fix("ALTER TABLE t ALTER COLUMN c TYPE varchar(256);"), @"ALTER TABLE t ALTER COLUMN c TYPE text;");
221+
}
222+
223+
#[test]
224+
fn fix_multiple_varchar_columns() {
225+
assert_snapshot!(fix("CREATE TABLE t (a varchar(100), b varchar(255), c varchar(50));"), @"CREATE TABLE t (a text, b text, c text);");
226+
}
227+
228+
#[test]
229+
fn fix_pgcatalog_varchar() {
230+
assert_snapshot!(fix("CREATE TABLE t (c pg_catalog.varchar(100));"), @"CREATE TABLE t (c text);");
231+
}
165232
}

crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_text_field__test__adding_column_non_text_err.snap

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,18 @@ expression: errors
1010
help: Some(
1111
"Use a `TEXT` field with a `CHECK` constraint.",
1212
),
13-
fix: None,
13+
fix: Some(
14+
Fix {
15+
title: "Replace with `text`",
16+
edits: [
17+
Edit {
18+
text_range: 56..68,
19+
text: Some(
20+
"text",
21+
),
22+
},
23+
],
24+
},
25+
),
1426
},
1527
]

crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_text_field__test__create_table_with_pgcatalog_varchar_err.snap

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,18 @@ expression: errors
1010
help: Some(
1111
"Use a `TEXT` field with a `CHECK` constraint.",
1212
),
13-
fix: None,
13+
fix: Some(
14+
Fix {
15+
title: "Replace with `text`",
16+
edits: [
17+
Edit {
18+
text_range: 69..92,
19+
text: Some(
20+
"text",
21+
),
22+
},
23+
],
24+
},
25+
),
1426
},
1527
]

crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_text_field__test__create_table_with_varchar_err.snap

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,18 @@ expression: errors
1010
help: Some(
1111
"Use a `TEXT` field with a `CHECK` constraint.",
1212
),
13-
fix: None,
13+
fix: Some(
14+
Fix {
15+
title: "Replace with `text`",
16+
edits: [
17+
Edit {
18+
text_range: 111..123,
19+
text: Some(
20+
"text",
21+
),
22+
},
23+
],
24+
},
25+
),
1426
},
1527
]

crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_text_field__test__increase_varchar_size_err.snap

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,18 @@ expression: errors
1010
help: Some(
1111
"Use a `TEXT` field with a `CHECK` constraint.",
1212
),
13-
fix: None,
13+
fix: Some(
14+
Fix {
15+
title: "Replace with `text`",
16+
edits: [
17+
Edit {
18+
text_range: 89..102,
19+
text: Some(
20+
"text",
21+
),
22+
},
23+
],
24+
},
25+
),
1426
},
1527
]

0 commit comments

Comments
 (0)