sql-review
Skill0 starsChanged 9 days agoMITView on GitHub
Review SQL in application code and .sql/migration files - SQL injection through string building (also in ORM raw queries), UPDATE/DELETE without WHERE, SELECT *, N+1 queries, missing indexes, missing transactions, lost updates, non-sargable predicates, unbounded result sets, NULL pitfalls and risky migrations. Use when asked to check/review/audit SQL, queries, database access code, ORM usage, migrations or "is my query safe/fast".
10 other projects use a version of this.
Adopted by
Most recently taken up by
- polardb/polardbx-skillstheir own version, first seen Nov 8, 2026
- Lanqiao-Luca/ai-java-workflowtheir own version, first seen Nov 8, 2026
- z-Zihan/Evirtheir own version, first seen Oct 13, 2026
- analyticsengineering/ae-toolkittheir own version, first seen Oct 12, 2026
- GabrielHenriqueCA/cortex-aitheir own version, first seen Oct 11, 2026
- kyle-chalmers/streamsnowtheir own version, first seen Oct 11, 2026
Used with
Projects with it also use code-review.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
GoogleSkillcode-review
Adversarial systems, concurrency, memory-model, and architecture code review protocol. Use this skill whenever asked to review code, PRs, diffs, or branches in Filament.
Also in 4 projects that use this
Other versions10 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 10
- Lanqiao-Luca/ai-java-workflow★ 220same name
- kyle-chalmers/streamsnow★ 17same name
- z-Zihan/Evir★ 11same name
- polardb/polardbx-skills★ 8same name
- analyticsengineering/ae-toolkit★ 3same name
- gmanch94/claude-code-aidlc-template★ 2same name
- Jiplet/transformation-os★ 2same name
- dennisrongo/claude-skills★ 1same name
- GabrielHenriqueCA/cortex-ai★ 1same name
- bt2go/claude-skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository28 other files it gives its agents.
- accessibility-auditSkill
- api-design-reviewSkill
- architecture-reviewSkill
- complexity-checkSkill
- concurrency-reviewSkill
- config-reviewSkill
- cpp-google-styleSkill
- csharp-google-styleSkill
- dead-code-finderSkill
- dependency-auditSkill
- doc-comment-auditSkill
- error-handling-reviewSkill
- full-reviewSkill
- java-google-styleSkill
- logging-reviewSkill
- markdown-readme-google-styleSkill
- naming-reviewSkill
- owasp-security-reviewSkill
- performance-reviewSkill
- privacy-reviewSkill
- python-google-styleSkill
- regex-reviewSkill
- repo-hygieneSkill
- review-without-fixingSkill
- secrets-scanSkill
- shell-google-styleSkill
- test-coverage-reviewSkill
- todo-auditSkill
The file
We split this skill into the rules it gives an agent
4 rules. 0 are common, 3 are distinctive, and 1 is very specific to this project.
0
Common
Most of the 8 edited versions we read keep these.
3
Distinctive
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 17
Read the schema (migrations, DDL, ORM models) for SQ5/SQ10.
- Very specific: line 18
Use a linter if installed (never install it.
- Distinctive: line 61
Every finding has a concrete location.
- Distinctive: line 65
Do not change code. Apply fixes only when the user explicitly asks for it.
“Common” is measured: kept by at least 6 in 10 of the 8 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
SQL review
Review only: report findings, never change queries, schemas or migrations unless the user explicitly asks. Never run queries, EXPLAIN ANALYZE or migrations against a real database without asking - they can be slow, lock tables or change data.
Scope
Check the files/directories the user names, otherwise the whole repo: .sql files, migrations (migrations/, db/migrate/, Flyway V*__*.sql, Liquibase, EF Migrations/, Alembic versions/), and code that builds or runs queries. Skip .git/, build output, vendor/, node_modules/, .venv/, generated code (EF model snapshots, ORM-generated clients) and seed/test data dumps.
Steps
- Detect the database (connection strings, drivers, migration tool, dialect hints) and the data access stack (table below).
- Find query construction: grep for
SELECT|INSERT|UPDATE|DELETEin strings, raw-query APIs (execute,query,raw,FromSqlRaw,$queryRawUnsafe,createNativeQuery,text(), and string building near them (+, f-strings,%,.format,${},Sprintf,String.format,$"..."). - For each query, trace where the dynamic parts come from (user input, config, constants) and check SQ1-SQ14.
- Read the schema (migrations, DDL, ORM models) for SQ5/SQ10. Without a schema, SQ5 findings are "possible".
- Use a linter if installed (never install it; mention it if it would help):
sqlfluff lintfor .sql files,squawkfor Postgres migrations,semgrepwith SQL injection rules. - Report (format below).
Rules
- SQ1 error: SQL injection - dynamic values concatenated/formatted into the query instead of bound parameters (also inside ORM raw APIs). Dynamic identifiers (table, column,
ORDER BY,ASC/DESC) can't be parameterized and need an allowlist. - SQ2 error:
UPDATE/DELETEwithoutWHERE, or with aWHEREclause that can end up empty when built dynamically - SQ3 warning:
SELECT *in application code (over-fetching; breaks mapping when the schema changes) - SQ4 warning: N+1 - a query inside a loop over the results of another query; ORM lazy loading inside loops
- SQ5 warning: missing index (possible) for columns used in frequent
WHERE/JOIN/ORDER BY; foreign keys without index - SQ6 error: multi-statement write that must be atomic without a transaction; warning: transaction kept open during network calls or user interaction
- SQ7 warning: lost update - read value, compute, write back without locking or version check (
SELECTthenUPDATEwith the computed value) - SQ8 warning: non-sargable predicate or implicit conversion: function on an indexed column (
WHERE LOWER(email) = ?,DATE(created_at) = ?), leading wildcardLIKE '%x', comparing text to number - SQ9 warning: unbounded result set for user-facing lists (no
LIMIT/pagination);LIMITwithoutORDER BY(non-deterministic pages) - SQ10 warning: risky migration: long table locks (index creation without
CONCURRENTLY/ONLINE, rewriting large tables, addingNOT NULLwithout default on large tables depending on DB version), no down/rollback path, schema and data changes mixed - SQ11 error:
= NULL/<> NULLinstead ofIS NULL; warning:NOT IN (subquery)where the subquery can returnNULL(returns no rows) - SQ12 warning: connections/cursors not closed or no pool →
error-handling-reviewEH6; credentials in connection strings →secrets-scan - SQ13 info:
DISTINCT/GROUP BYused to hide duplicate rows from a wrong join - SQ14 info: dialect-specific syntax in a project that claims to support several databases
Safe vs. unsafe per stack
| Stack | Safe | Unsafe (SQ1) |
| JDBC | PreparedStatement with ? | Statement.execute("..." + x) |
| JPA / Hibernate | setParameter, Criteria API | createQuery/createNativeQuery with concatenation |
| ADO.NET / Dapper | SqlParameter, Dapper new { id } | interpolation into CommandText |
| EF Core | LINQ, FromSql($"..."), FromSqlInterpolated | FromSqlRaw/ExecuteSqlRaw with a pre-built string |
| Python DB-API (sqlite3, psycopg) | cur.execute(sql, params) with ?/%s | f-string, %, .format into sql |
| SQLAlchemy | text("... :id") with bind params, ORM | text(f"...") |
| Django | ORM, raw(sql, params) | raw(f"..."), extra() with strings |
| node-postgres / mysql2 | query(text, values) with $1/? | template literal into text |
| Prisma | $queryRaw`...${x}` (tagged) | $queryRawUnsafe with concatenation |
| Knex | query builder, raw('?', [x]) | raw(`... ${x}`) |
Go database/sql, GORM | Query(sql, args...), Where("x = ?", v) | fmt.Sprintf into Query/Where |
| PHP PDO | prepare + execute | query("..." . $x) |
False positives to drop
Concatenation of constant strings only (no external input) · identifiers from a hard-coded allowlist · SELECT * in ad-hoc scripts, EXISTS (SELECT * ...) and COUNT(*) · N+1 on tiny bounded lists (report as info) · migrations for tables that are known to be small.
Report
In the user's language, grouped by file:
path/to/file:line - error|warning|info - <ID> <rule> - <what can happen, e.g. "name=' OR 1=1 -- returns all users"> - direction: <what the fix must achieve, e.g. "bind the value as a parameter">- Every finding has a concrete location; for SQ1 name the source of the dynamic value. Don't write working attack payloads beyond a minimal illustration like the one above.
- Mark findings that depend on unknown data size or schema as "possible".
- Bulk hits with one root cause (e.g. one query helper that concatenates): report once with count and 2-3 call sites.
- End with a summary: database and access stack, findings per severity, then the 3 most important things to fix first.
- Do not change code. Apply fixes only when the user explicitly asks for it.
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.

