Skip to content

feat(rules): add W015 join-function-on-column#33

Merged
Pawansingh3889 merged 3 commits intoPawansingh3889:mainfrom
mvanhorn:osc/5-add-w015-join-function-on-column
May 2, 2026
Merged

feat(rules): add W015 join-function-on-column#33
Pawansingh3889 merged 3 commits intoPawansingh3889:mainfrom
mvanhorn:osc/5-add-w015-join-function-on-column

Conversation

@mvanhorn
Copy link
Copy Markdown
Contributor

Closes #5.

Adds W015 join-function-on-column. The rule mirrors W003 but checks JOIN ... ON predicates instead of WHERE clauses. Both patterns destroy index-based join performance the same way.

Implementation

sql_guard/rules/warnings.py: new JoinFunctionOnColumn rule. Same shape as FunctionOnIndexedColumn (W003), with one difference -- the regex anchors the function search to the ON predicate so it stops at the next clause keyword (WHERE / GROUP BY / ORDER BY / HAVING / next JOIN / UNION). Without that bound, single-line queries with a clean JOIN and a dirty WHERE would trip W015 even though W003 already owns that case.

Function list matches W003: YEAR, MONTH, DAY, DATE, UPPER, LOWER, TRIM, CAST, CONVERT, SUBSTRING, COALESCE.

Wiring

  • sql_guard/rules/__init__.py: import + registration in ALL_RULES.
  • tests/fixtures/warnings.sql: fixture entry exercising the rule.
  • tests/test_new_rules.py: 5 unit tests -- happy path (UPPER, YEAR), passing case (materialized columns), W003-only case (function in WHERE), and the false-positive regression (clean JOIN + dirty WHERE on the same line).
  • tests/test_rules.py: registry counts updated (34 -> 35 rules, 24 -> 25 warnings) and an integration test verifying W015 fires from the fixture.

Verification

python3 -m pytest tests/ --ignore=tests/test_structural.py -q
# 125 passed, 1 skipped

The test_structural.py failure pre-exists on upstream/main and is unrelated to this change.

@codecov-commenter
Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@Pawansingh3889
Copy link
Copy Markdown
Owner

Rule's solid. The negative lookahead stopping at the next clause keyword is exactly right, and the clean-JOIN-dirty-WHERE test is the one I'd have asked for.

CI's only blocker is the CHANGELOG entry under [Unreleased] / ### Added. Same shape as the W023 line that just merged in #34. While you're rebasing, please also add a README rule-table row for W015 and bump the key-numbers (Rules, warnings sub-count, the intro paragraph).

One sequencing note: I merged #34 first, so main is now at 35 rules / 25 warnings. The assertions in test_rules.py need 35 → 36 and 25 → 26, and test_25_warnings becomes test_26_warnings. The rev-pin warnings you saw in pr-sop output are now fixed on main too, so a fresh rebase will clear those.

Good to merge once those are in. Thanks for the second one this week.

mvanhorn and others added 3 commits May 2, 2026 11:23
Adds a new warning rule that catches function-wrapped columns in
JOIN ... ON clauses, mirroring W003 which only checks the WHERE
clause. Both patterns are equally index-hostile.

Detects functions on either side of the equality predicate:
- YEAR/MONTH/DAY/DATE on date columns
- UPPER/LOWER/TRIM/CAST/CONVERT/SUBSTRING/COALESCE on text columns

Closes Pawansingh3889#5.
Without bounding the inner '.*', a single-line query with a clean JOIN
predicate and a dirty WHERE function (e.g. UPPER on a column) would
trip W015 even though W003 already owns that case.

The new regex anchors the function search to the ON predicate by
refusing to cross WHERE / GROUP BY / ORDER BY / HAVING / a subsequent
JOIN / UNION before finding the function.

Adds a regression test covering the false-positive case.
@Pawansingh3889 Pawansingh3889 force-pushed the osc/5-add-w015-join-function-on-column branch from 19c65de to ee7a469 Compare May 2, 2026 10:25
@Pawansingh3889
Copy link
Copy Markdown
Owner

Picked this back up — rebased on main, added the CHANGELOG entry, README rule-table row, and the key-numbers bump. CI is green. Squashing now. Thanks for the patience and for shipping the third one this month, much appreciated.

@Pawansingh3889 Pawansingh3889 merged commit 73497e8 into Pawansingh3889:main May 2, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

rule: W015 join-function-on-column - warn on JOIN ... ON f(col) = ...

3 participants