Skip to main content

rigsql_rules/references/
rf01.rs

1use rigsql_core::SegmentType;
2
3use crate::rule::{CrawlType, Rule, RuleContext, RuleGroup};
4use crate::violation::LintViolation;
5
6/// RF01: References cannot reference objects not present in FROM clause.
7///
8/// Checks that table/alias qualifiers used in SELECT, WHERE, etc. actually
9/// exist in the FROM or JOIN clauses of the query.
10#[derive(Debug, Default)]
11pub struct RuleRF01;
12
13impl Rule for RuleRF01 {
14    fn code(&self) -> &'static str {
15        "RF01"
16    }
17    fn name(&self) -> &'static str {
18        "references.from"
19    }
20    fn description(&self) -> &'static str {
21        "References cannot reference objects not present in FROM clause."
22    }
23    fn explanation(&self) -> &'static str {
24        "Table or alias qualifiers used in SELECT, WHERE, GROUP BY, and other clauses \
25         must correspond to a table or alias declared in the FROM or JOIN clauses. \
26         Referencing an undeclared alias like 'vee.a' when only 'foo' is in FROM \
27         is an error."
28    }
29    fn groups(&self) -> &[RuleGroup] {
30        &[RuleGroup::References]
31    }
32    fn is_fixable(&self) -> bool {
33        false
34    }
35
36    fn crawl_type(&self) -> CrawlType {
37        CrawlType::Segment(vec![SegmentType::SelectStatement])
38    }
39
40    fn eval(&self, _ctx: &RuleContext) -> Vec<LintViolation> {
41        // Stub: not yet implemented.
42        vec![]
43    }
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49    use crate::test_utils::lint_sql;
50
51    #[test]
52    fn test_rf01_stub_no_false_positives() {
53        let violations = lint_sql("SELECT id, name FROM users WHERE active = 1", RuleRF01);
54        assert_eq!(violations.len(), 0);
55    }
56
57    #[test]
58    fn test_rf01_stub_no_false_positives_join() {
59        let violations = lint_sql(
60            "SELECT u.id, o.total FROM users u JOIN orders o ON u.id = o.user_id",
61            RuleRF01,
62        );
63        assert_eq!(violations.len(), 0);
64    }
65}