@@ -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
1010use 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+
5275fn 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) ]
7094mod 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}
0 commit comments