feat: add W022 cross-join-explicit rule#31
feat: add W022 cross-join-explicit rule#31Pawansingh3889 merged 2 commits intoPawansingh3889:mainfrom
Conversation
There was a problem hiding this comment.
Thanks for your first PR on sql-sop! Quick checks:
pytest -qandruff check .pass locally- Every new rule has both a "fires on bad SQL" test AND a
"does NOT fire on safe SQL" test - Rule IDs (
E001,W001, …) are public API — don't renumber
or rename existing ones without the deprecation process in
GOVERNANCE.md CHANGELOG.md[Unreleased]entry for any user-facing change
First-PR-wins on the linked issue applies for 7 days. The
maintainer will review within 14 days of your last response.
|
Thanks @vibeyclaw, appreciate the fast turnaround on #8. The code is small, the tests pass locally, and the structure mirrors W019's shape correctly. A few real things to address before this lands: False positives in string literals and comments. The regex
I reproduced all three locally. Each returns a Finding when it shouldn't. W020 (truncate-table) has a E402 ruff error blocking CI. Missing CHANGELOG entry. The
Worth knowing but not blocking: the rule won't catch Test coverage suggestion: once the false-positive fix lands, add the three negative cases (string literal, line comment, block comment) to your test set so the regression surface is covered. The W020 tests are a good template. Ping me here once these are addressed and I'll re-review. Genuinely good first PR, the implementation is clean and the test structure is right. |
Single-file CLI that prints copy-paste-ready snippets for every file
that needs an edit when adding a new rule:
- the rule class for sql_guard/rules/{warnings,errors,structural}.py
- the registration in sql_guard/rules/__init__.py
- the fixture line
- the two tests (fires + does-not-fire)
- the README rule table row
- the CHANGELOG entry under [Unreleased]
- a reminder to bump README Key Numbers
Output mirrors the W019 (CountDistinctUnbounded) shape that
CONTRIBUTING.md and the v0.7 milestone reference.
Includes an explicit reminder to put the test-file import at the top
of tests/test_new_rules.py to avoid the E402 ruff error that's been
catching first-time contributors (most recently #31).
Severity and target file are inferred from the rule code prefix:
E -> error, errors.py
W -> warning, warnings.py
T -> warning, warnings.py
S -> warning, structural.py
P -> error, python_source.py
a9d3ea0 to
e5e22e9
Compare
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Adds a new warning rule W022 that detects explicit CROSS JOIN usage, which produces a Cartesian product and is rarely intentional. - Fires on any explicit CROSS JOIN statement - Single-line rule using regex check - Users can suppress with inline '-- noqa: W022' comment - Adds 5 unit tests covering: detection, case-insensitivity, pass cases Closes Pawansingh3889#8
e5e22e9 to
f7ebd34
Compare
|
Took this over the line. Rebased on top of #33 and #32 which both landed in the last hour, so the count assertions are now 38/28. While I was in the rule, tightened the regex to strip trailing -- line comments before matching, since -- avoid CROSS JOIN here was tripping it as a false positive. Added a regression test for the comment case. Suggestion text now points at -- sql-guard: disable=W022 (the project-wide convention) rather than the bare noqa form. CHANGELOG / README rule-table row / key-numbers updated. Squashing once CI settles. Thanks for the rule, the calendar-grid edge case is exactly the framing this needed. |
Summary
Implements the W022 rule requested in #8.
Adds a new warning rule that detects explicit
CROSS JOINusage, which produces a Cartesian product and is rarely intentional outside of calendar-grid or lookup-table generation patterns.Changes
sql_guard/rules/warnings.py: AddedCrossJoinExplicitclass (W022) with a single-line regex checksql_guard/rules/__init__.py: RegisteredCrossJoinExplicitin the rule registry andALL_RULESlisttests/test_new_rules.py: Added 5 unit tests covering detection, case-insensitivity, and pass casesBehavior
Flags:
Passes:
Suppress with noqa:
Closes #8