sqrust_rules/lint/
alter_table_drop_column.rs1use sqrust_core::{Diagnostic, FileContext, Rule};
2use sqlparser::ast::{AlterTableOperation, Statement};
3
4pub struct AlterTableDropColumn;
5
6impl Rule for AlterTableDropColumn {
7 fn name(&self) -> &'static str {
8 "Lint/AlterTableDropColumn"
9 }
10
11 fn check(&self, ctx: &FileContext) -> Vec<Diagnostic> {
12 if !ctx.parse_errors.is_empty() {
14 return Vec::new();
15 }
16
17 let mut diags = Vec::new();
18 let source = &ctx.source;
19 let source_upper = source.to_uppercase();
20
21 for stmt in &ctx.statements {
22 if let Statement::AlterTable { operations, .. } = stmt {
23 for op in operations {
24 if matches!(op, AlterTableOperation::DropColumn { .. }) {
25 let (line, col) =
26 find_keyword_position(source, &source_upper, "ALTER");
27 diags.push(Diagnostic {
28 rule: self.name(),
29 message:
30 "ALTER TABLE DROP COLUMN is irreversible; verify all dependent \
31 code has been updated"
32 .to_string(),
33 line,
34 col,
35 });
36 }
37 }
38 }
39 }
40
41 diags
42 }
43}
44
45fn find_keyword_position(source: &str, source_upper: &str, keyword: &str) -> (usize, usize) {
49 let kw_len = keyword.len();
50 let bytes = source_upper.as_bytes();
51 let text_len = bytes.len();
52
53 let mut search_from = 0usize;
54 while search_from < text_len {
55 let Some(rel) = source_upper[search_from..].find(keyword) else {
56 break;
57 };
58 let abs = search_from + rel;
59
60 let before_ok = abs == 0
61 || {
62 let b = bytes[abs - 1];
63 !b.is_ascii_alphanumeric() && b != b'_'
64 };
65 let after = abs + kw_len;
66 let after_ok = after >= text_len
67 || {
68 let b = bytes[after];
69 !b.is_ascii_alphanumeric() && b != b'_'
70 };
71
72 if before_ok && after_ok {
73 return offset_to_line_col(source, abs);
74 }
75 search_from = abs + 1;
76 }
77
78 (1, 1)
79}
80
81fn offset_to_line_col(source: &str, offset: usize) -> (usize, usize) {
83 let before = &source[..offset];
84 let line = before.chars().filter(|&c| c == '\n').count() + 1;
85 let col = before.rfind('\n').map(|p| offset - p - 1).unwrap_or(offset) + 1;
86 (line, col)
87}