code-quality-sql
Skill345 starsChanged 35 days agoApache-2.0View on GitHub
Use when writing or reviewing SQL craft and style (queries, DDL, migrations, test fixtures) anywhere in this repo, or when asked for "worldclass"/"clean" SQL. Covers explicit column lists, CTEs, JOIN explicitness, SARGable predicates, DDL/type discipline, and portability across MySQL/Postgres (source) and ClickHouse (target).
In this repository17 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- .github/copilot-instructions.mdCopilot instructions
- clickhouse-sink-reviewSkill
- code-quality-architectureSkill
- code-quality-bashSkill
- code-quality-goSkill
- code-quality-jvmSkill
- code-quality-pythonSkill
- code-reuse-firstSkill
- code-reuse-reviewSkill
- design-note-debtSkill
- destructive-operation-safetySkill
- mandatory-code-change-validationSkill
- pr-self-reviewSkill
- repro-harness-negative-proofSkill
- sink-connector-mysql-source-of-truthSkill
The file
We split this skill into the rules it gives an agent
2 rules. About 0 are common, 1 is distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 68
Keep the indexed column "clean" on the left of the predicate — never wrapped in a function, never implicitly converted.
- Very specific: line 94
Run over every changed SQL statement (files and SQL built in code) during pr-self-review's per-language pass.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Worldclass SQL
Overview
Readable, correct, performant SQL across ClickHouse (the replication
target), and MySQL/Postgres (the source of truth). ClickHouse-specific
design (engine selection, ORDER BY keys, partitioning, FINAL,
materialized views, codecs, sparse indexes) is a distinct body of
knowledge from general SQL craft — consult ClickHouse's own documentation
and this project's doc/clickhouse_engines.md and specs/07-type-system,
specs/08-schema-catalog domains for the engine-level rules that matter
for this connector. This skill is general SQL craft.
When to Use
- Writing or reviewing any
.sqlquery, DDL, or migration - A user asks for "clean / worldclass / readable" SQL
- Reviewing a query for SARGability / index-usage problems
Core Craft (portable)
Why these: clarity and index-friendliness. Most slow queries come from hidden
full scans (non-SARGable predicates) and most bugs from SELECT * plus implicit
conversions.
- Explicit column lists, never
SELECT *—*hides intent, breaks on schema change, inflates I/O. (Exception: throwaway exploration.) This matters doubly here: a schema drift between MySQL/Postgres and ClickHouse is exactly the class of bug this project exists to prevent, andSELECT *in comparison/verification tooling can hide a dropped column. - CTEs for readability — one logical step per CTE, composable and debuggable.
While debugging,
SELECT * FROM last_cteto inspect a stage. - Consistent casing — keywords UPPER, identifiers
snake_case. Pick one and hold it. - Meaningful aliases — descriptive, not
a/b. Always qualify columns in multi-table queries so origin is obvious. - Explicit JOIN types —
INNER JOIN/LEFT JOIN, never bareJOIN, never comma-joins. Join conditions inON, filters inWHERE. - Set-based over row-by-row — no cursors/loops where one statement works.
- Prefer JOINs to correlated subqueries, but confirm with
EXPLAIN— modern optimizers often rewrite them equivalently.
-- BAD
SELECT * FROM orders o
WHERE (SELECT count(*) FROM items i WHERE i.order_id = o.id) > 5; -- correlated, *
-- GOOD
WITH item_counts AS (
SELECT order_id, count(*) AS item_count
FROM items
GROUP BY order_id
)
SELECT o.id, o.customer_id, ic.item_count
FROM orders AS o
INNER JOIN item_counts AS ic ON ic.order_id = o.id
WHERE ic.item_count > 5;SARGability — the #1 performance rule
Keep the indexed column "clean" on the left of the predicate — never wrapped in a function, never implicitly converted.
- No functions on indexed columns in
WHERE:WHERE YEAR(order_date) = 2023forces a full scan. Rewrite as a range:WHERE order_date >= '2023-01-01' AND order_date < '2024-01-01'. Same forLEFT(),COALESCE(),TRIM()on the column side. - No implicit conversions — comparing mismatched types casts the column and
kills index use (string ↔ numeric,
NVARCHARvsVARCHAR). Cast the value, never the column. - No leading-wildcard
LIKE '%x%'— non-SARGable; prefer trailing'x%'.
DDL Quality
- Explicit, narrowest correct types. Match types across joined/compared columns
to avoid implicit conversions. On the ClickHouse side, type choice directly
affects how DDL translation and the column-kind rules (ALIAS/MATERIALIZED/
ordinary) apply — see
sink-connector-mysql-source-of-truth. - Constraints (NOT NULL, PK/FK, CHECK, UNIQUE) in MySQL/Postgres enforce integrity at the DB. ClickHouse does not enforce constraints — model invariants upstream, at the source.
- Naming conventions —
snake_case, FK columns as<entity>_id, indexes named by table+columns; choose singular-vs-plural and hold it. - Migrations — versioned, forward-only, reviewed. Re-run
EXPLAINon hot queries after any column-type change (a cast can silently shift sides).
Deep Review Checklist (SQL)
Run over every changed SQL statement (files and SQL built in code) during
pr-self-review's per-language pass. Report a hit as the broken invariant
with file:line and a concrete trace.
- Injection — statements built by concatenating values or identifiers; identifiers not quoted when names can be reserved words or contain special characters.
- NULL semantics —
= NULL,NOT IN (subquery containing NULL)returning nothing, aggregates skipping NULLs,COALESCEhiding real NULLs in comparisons. This is especially load-bearing here: ordinary columns must bind a sourceNULLfaithfully, not silently coerce it. - Join cardinality — an INNER join dropping rows a LEFT join must keep; a fan-out duplicating rows that are then summed.
- Non-determinism —
LIMITwithoutORDER BY,any()or a bareGROUP BYpicking arbitrary values, ties in window ordering. - Types — FLOAT for exact values, implicit casts that truncate or overflow, DECIMAL scale mismatch, signed vs unsigned, comparisons under different collations or case rules.
- Time — naive timestamps across systems in different zones,
DateTimevsDateTime64precision, inclusive/exclusive range bounds. - Unbounded work — missing partition/primary-key predicates,
SELECT *, N+1 query loops, no LIMIT on interactive queries. On replicated/target tables this also risks Invariant I14 (Bounded Bookkeeping) — an unbounded scan needs anI14-scan-allowed:marker or it should be rejected. - Multi-statement writes that must be atomic but are not in a transaction (on ClickHouse: not idempotent on retry).
- DDL safety — table rewrites, locks,
DROP/TRUNCATEwithout bounded blast radius (seedestructive-operation-safety), mutations where a lightweight operation exists.
Anti-Patterns
SELECT * · functions/implicit casts on indexed columns (non-SARGable) ·
leading-wildcard LIKE · N+1 per-row query patterns · comma-joins · unqualified
columns in multi-table queries · trusting a "rewrite correlated subquery" rule
without checking EXPLAIN.
Sources
sqlstyle.guide (Holywell) · mattm/sql-style-guide · Meltano SQL Style Guide ·
Baeldung: SQL SARGability. ClickHouse design: doc/clickhouse_engines.md and
ClickHouse's own documentation.
Cross-References
pr-self-review, sink-connector-mysql-source-of-truth,
destructive-operation-safety.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

