Skip to content

Commit 98dc78d

Browse files
kvlongeampagent
andauthored
docs: polish the README header, opening, demo and benchmark table (#10)
* docs: polish the README header, opening, demo and benchmark table Use transparent light and dark header logos in a picture element, with the light logo as the fallback for PyPI. Merge the speed line and the navigation into one centred block and make the intro left-aligned. Re-record the check-fix demo to show a NULL comparison, a safe fix that removes an unused CTE, a custom Rule finding, and the unsafe IS NULL fix applied only with --unsafe-fixes. Name the ratio column "Time relative to sqlclean check" and move Quick start after Speed. Co-authored-by: Kevin Longe <kvlonge@gmail.com> * docs: trim the README logo padding and explain recovering a release pull request Co-authored-by: Kevin Longe <kvlonge@gmail.com> --------- Co-authored-by: Amp <amp@ampcode.com>
1 parent ae48505 commit 98dc78d

8 files changed

Lines changed: 70 additions & 54 deletions

File tree

‎.github/RELEASING.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ Documentation edits usually do release, on purpose: `make skills` copies the doc
2626
installed skill stays in step with the docs. A homepage or styling change touches only `website/`
2727
and does not.
2828

29+
Merge pull requests one at a time, each with its branch up to date with `main`. The release
30+
workflow only trusts a release base whose tree passed Verify on the pull request that produced
31+
it. If two pull requests merge back to back, `main` holds a combination no pull request verified,
32+
and the release workflow stops before it refreshes the release pull request's lockfiles. A later
33+
run that leaves the release pull request unchanged does not repair it. To recover, close the
34+
release pull request, then merge the next up-to-date pull request; Release Please opens a fresh
35+
release pull request from the verified tree.
36+
2937
## One-time setup
3038

3139
A repository administrator does these once, in a browser:

‎.github/demos/check-fix.gif‎

125 KB
Loading

‎.github/sqlclean-logo-dark.png‎

75.5 KB
Loading

‎.github/sqlclean-logo-light.png‎

86.4 KB
Loading

‎README.md‎

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,44 @@
11
<p align="center">
2-
<img src="https://raw.githubusercontent.com/sqlstack-io/sqlclean/main/.github/sqlclean-logo.png" alt="SQLClean" width="100%">
2+
<picture>
3+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/sqlstack-io/sqlclean/main/.github/sqlclean-logo-dark.png">
4+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/sqlstack-io/sqlclean/main/.github/sqlclean-logo-light.png">
5+
<img src="https://raw.githubusercontent.com/sqlstack-io/sqlclean/main/.github/sqlclean-logo-light.png" alt="SQLClean" width="100%">
6+
</picture>
37
</p>
48

59
<h2 align="center">The fastest SQL linter.</h2>
610

711
<p align="center">
812
<strong>50× faster than sqruff. Lint 10,000 SQL files in under a second.</strong> <a href="https://sqlclean.io/docs/benchmarks/">Benchmarks</a>
9-
</p>
10-
11-
<p align="center">
12-
Catch SQL mistakes, apply safe fixes, and format consistently. Add your own rules in Python.
13-
</p>
14-
15-
<p align="center">
13+
<br>
1614
<a href="https://sqlclean.io">Website</a> ·
1715
<a href="https://sqlclean.io/docs/quickstart/">Get started</a> ·
1816
<a href="https://sqlclean.io/docs/">Docs</a> ·
1917
<a href="https://sqlclean.io/docs/benchmarks/">Benchmarks</a>
2018
</p>
2119

20+
Catch SQL mistakes, apply safe fixes, and format consistently. Add your own rules in Python.
21+
SQLClean parses and checks SQL in Rust, and runs your Python Rules on statements it has already
22+
parsed.
23+
2224
```bash
2325
uv tool install sqlclean # or: pip install sqlclean
2426
```
2527

2628
<p align="center">
27-
<img src="https://raw.githubusercontent.com/sqlstack-io/sqlclean/main/.github/demos/check-fix.gif" alt="sqlclean check reports three findings, then sqlclean fix applies two fixes and formats the file" width="100%">
29+
<img src="https://raw.githubusercontent.com/sqlstack-io/sqlclean/main/.github/demos/check-fix.gif" alt="sqlclean check reports an unused CTE, a temporary table from a custom Rule and a comparison with NULL; sqlclean fix removes the CTE and formats the file; sqlclean fix --unsafe-fixes rewrites = NULL to IS NULL" width="100%">
2830
</p>
2931

30-
`sqlclean check` reports a bare `JOIN`, a `COUNT(1)` and a temporary table from a custom Rule.
31-
`sqlclean fix` applies the two fixes and formats the file; the custom Rule's finding has no fix,
32-
so it stays.
32+
`sqlclean check` reports an unused CTE, a temporary table from a custom Rule and a `= NULL`
33+
comparison that is never true. `sqlclean fix` applies the safe fix, removing the CTE, and formats
34+
the file. It leaves `= NULL` alone because rewriting it to `IS NULL` changes which rows match;
35+
`sqlclean fix --unsafe-fixes` applies that fix. The custom Rule's finding has no fix, so it stays.
3336

3437
## Speed
3538

3639
Linting the same 10,282 Snowflake SQL files on 4 CPUs, with no cache:
3740

38-
| Command | Wall time | vs `sqlclean check` |
41+
| Command | Wall time | Time relative to `sqlclean check` |
3942
|---|---:|---:|
4043
| `sqlclean check` (default Rules) | **0.81 s** | 1× |
4144
| `sqlclean check --select SQC` (all Rules) | **1.33 s** | 1.6× |
@@ -49,6 +52,18 @@ The tools don't check the same things, so see the
4952
[benchmarks](https://sqlclean.io/docs/benchmarks/) for coverage, the corpus, the method and how
5053
to run it yourself.
5154

55+
## Quick start
56+
57+
```bash
58+
sqlclean check # report findings in every .sql file under the directory
59+
sqlclean fix # apply safe fixes, then format
60+
sqlclean format # rewrite files in the canonical layout
61+
```
62+
63+
Add a `sqlclean.toml` to choose a dialect, files or Rules. See the
64+
[quickstart](https://sqlclean.io/docs/quickstart/) and
65+
[configuration](https://sqlclean.io/docs/configuration/).
66+
5267
## Correct and safe
5368

5469
- **Rules for SQL that runs but is wrong.** Built-in Rules flag comparisons with `NULL`, `NOT IN`
@@ -88,18 +103,6 @@ Point `[rules] custom = ["sql_rules"]` in `sqlclean.toml` at it. See
88103
[custom Rules](https://sqlclean.io/docs/custom-rules/overview/) and
89104
[testing custom Rules](https://sqlclean.io/docs/custom-rules/testing/).
90105

91-
## Quick start
92-
93-
```bash
94-
sqlclean check # report findings in every .sql file under the directory
95-
sqlclean fix # apply safe fixes, then format
96-
sqlclean format # rewrite files in the canonical layout
97-
```
98-
99-
Add a `sqlclean.toml` to choose a dialect, files or Rules. See the
100-
[quickstart](https://sqlclean.io/docs/quickstart/) and
101-
[configuration](https://sqlclean.io/docs/configuration/).
102-
103106
## Integrations
104107

105108
```yaml

‎website/recordings/README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ scripts are the source; the rendered GIF, MP4 and PNG files go to `out/`, which
66

77
| Demo | Shows |
88
|------|-------|
9-
| `check-fix` | `sqlclean check` reports built-in and custom findings, and `sqlclean fix` fixes and formats. |
9+
| `check-fix` | `sqlclean check` reports built-in and custom findings, `sqlclean fix` applies the safe fix and formats, and `sqlclean fix --unsafe-fixes` applies the unsafe one. |
1010

1111
The README uses `check-fix`, copied into `.github/demos/`.
1212

‎website/recordings/prepare.sh‎

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,25 @@ mkdir -p "$dir"
99
cd "$dir"
1010
case "$demo" in
1111
check-fix)
12-
# One messy query: a bare JOIN, COUNT(1) and a temporary table that a custom Rule forbids.
12+
# One query with a NULL comparison, an unused CTE and a temporary table that a custom Rule forbids.
1313
mkdir -p models sql_rules
1414
cat > sqlclean.toml <<'TOML'
1515
dialect = "duckdb"
1616
1717
[rules]
18-
select = ["SQC025", "XSQC"]
1918
custom = ["sql_rules"]
2019
TOML
2120
cat > models/orders.sql <<'SQL'
22-
select o.order_id, c.name, count(1) as items
23-
from orders o join tmp_customers c on o.customer_id = c.customer_id
24-
group by o.order_id, c.name
21+
with refunds as (
22+
select order_id from payments where status = 'refunded'
23+
)
24+
select o.order_id, c.name, o.total
25+
from orders o
26+
join tmp_customers c on o.customer_id = c.customer_id
27+
where o.shipped_at = null
2528
SQL
26-
cat > sql_rules/style.py <<'PY'
27-
from sqlclean import FixSafety, RuleContext, Statement, rule
29+
cat > sql_rules/naming.py <<'PY'
30+
from sqlclean import Finding, RuleContext, Statement, rule
2831
2932
3033
@rule(
@@ -33,28 +36,12 @@ from sqlclean import FixSafety, RuleContext, Statement, rule
3336
remediation="Read from the published table instead.",
3437
enabled_by_default=True,
3538
)
36-
def temporary_table(*, statement: Statement, ctx: RuleContext) -> list:
39+
def temporary_table(*, statement: Statement, ctx: RuleContext) -> list[Finding]:
3740
return [
3841
ctx.finding(subject=statement, node=table)
3942
for table in statement.tables
4043
if table.name.startswith("tmp_")
4144
]
42-
43-
44-
@rule(
45-
code="XSQCSTYLE001",
46-
message="COUNT(1) should be COUNT(*)",
47-
remediation="Write COUNT(*).",
48-
fixable=FixSafety.SAFE,
49-
enabled_by_default=True,
50-
)
51-
def count_one(*, statement: Statement, ctx: RuleContext) -> list:
52-
counts = {f.end + 1 for f in statement.functions if f.name.upper() == "COUNT"}
53-
return [
54-
ctx.finding(subject=statement, node=literal, fix=[ctx.replace(node=literal, text="*")])
55-
for literal in statement.literals
56-
if literal.text == "1" and literal.start in counts
57-
]
5845
PY
5946
;;
6047
*)

‎website/recordings/tapes/check-fix.tape‎

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Source tapes/common.tape
2-
Set Height 820
2+
Set Height 880
33
Output out/check-fix.gif
44
Output out/check-fix.mp4
55
Hide
@@ -14,8 +14,26 @@ Type "sqlclean check"
1414
Sleep 300ms
1515
Enter
1616
Wait@60s /\$\s*$/
17-
Sleep 3s
18-
Type "clear && sqlclean fix"
17+
Sleep 5s
18+
Hide
19+
Type "clear"
20+
Enter
21+
Sleep 300ms
22+
Show
23+
Type "sqlclean fix"
24+
Sleep 300ms
25+
Enter
26+
Wait@60s /\$\s*$/
27+
Sleep 1500ms
28+
Type "cat models/orders.sql"
29+
Enter
30+
Sleep 5s
31+
Hide
32+
Type "clear"
33+
Enter
34+
Sleep 300ms
35+
Show
36+
Type "sqlclean fix --unsafe-fixes"
1937
Sleep 300ms
2038
Enter
2139
Wait@60s /\$\s*$/
@@ -24,4 +42,4 @@ Type "cat models/orders.sql"
2442
Enter
2543
Sleep 1s
2644
Screenshot out/check-fix.png
27-
Sleep 8s
45+
Sleep 5s

0 commit comments

Comments
 (0)