# SQL Danger Checker

Paste SQL and flag destructive statements before you run them — DROP, TRUNCATE, and UPDATE/DELETE with no WHERE. Comment- and string-aware, in-browser.

## Run it

- **CLI:** `gizza tool sql-danger-checker "DROP TABLE users;
DELETE FROM sessions;
UPDATE accounts SET balance = 0;
SELECT * FROM orders WHERE id = 42;"`
- **Web:** https://gizza.ai/tools/sql-danger-checker/
- **Agents:** machine-readable descriptor (parameters JSON Schema) at https://gizza.ai/tools/sql-danger-checker/tool.json

## Inputs

- `sql` — SQL to scan _(field)_
- `dialect` — SQL dialect _(field)_
- `min_severity` — Minimum severity to report _(field)_
- `strict` — Strict — also flag guarded DELETE/UPDATE _(field)_
- `allow` — Allow (suppress categories) _(field)_
- `format` — Output format _(field)_

## Output

- Danger report (text)

## Query parameters

Open the tool pre-filled and auto-run via URL:

- `sql` — SQL to scan
- `dialect` — SQL dialect
- `min_severity` — Minimum severity to report
- `strict` — Strict — also flag guarded DELETE/UPDATE
- `allow` — Allow (suppress categories)
- `format` — Output format

Example: `https://gizza.ai/tools/sql-danger-checker/?sql=DROP%20TABLE%20users%3B%0ADELETE%20FROM%20sessions%3B%0AUPDATE%20accounts%20SET%20balance%20%3D%200%3B%0ASELECT%20%2A%20FROM%20orders%20WHERE%20id%20%3D%2042%3B&dialect=generic&min_severity=all&strict=true&allow=drop%2C%20truncate&format=text`

---

## About this tool

**SQL Danger Checker** is a static pre-flight review for raw SQL: paste one or more
statements and it flags the ones that can lose or overwrite data **before** you run
them. It never connects to a database and never executes anything — it reads the text
and classifies each statement, so it is safe to run against a query you have not
decided to execute yet.

It flags four kinds of destructive SQL:

- **`DROP DATABASE` / `DROP SCHEMA` / `DROP TABLE` and `TRUNCATE`** — *critical*, they
  permanently delete objects and every row in them.
- **`DROP` of another object (index, view, column …) and `ALTER … DROP …`** — *high*,
  they discard whatever the dropped object held.
- **Other `ALTER`** schema changes — *medium*, review and back up first.
- **`UPDATE` / `DELETE` with no `WHERE`** — or a trivially-true one such as
  `WHERE 1=1` — *high*, because they touch **every** row in the table.

### Worked example

Paste:

```sql
DROP TABLE users;
DELETE FROM sessions;
UPDATE accounts SET balance = 0;
SELECT * FROM orders WHERE id = 42;
```

and you get a report like:

```
3 danger(s) found (1 critical, 2 high, 0 medium, 0 low) in 4 statement(s) scanned

statement 1, line 1  CRITICAL  DROP-TABLE  DROP TABLE permanently removes the table and all of its data.
  DROP TABLE users;

statement 2, line 2  HIGH  DELETE-NO-WHERE  DELETE without a WHERE clause removes ALL rows in the table.
  DELETE FROM sessions;

statement 3, line 3  HIGH  UPDATE-NO-WHERE  UPDATE without a WHERE clause overwrites ALL rows in the table.
  UPDATE accounts SET balance = 0;
```

The `SELECT` is left alone. Each finding gives the statement number, line, severity, a
rule id, and the offending statement so you can jump straight to it. Choose **JSON**
output to pipe the same findings into a script or CI check.

### Options and limits

Set a **dialect** (MySQL additionally treats `#` as a line comment); raise the
**minimum severity** to hide low-risk findings; turn on **strict** to also surface
*guarded* `DELETE`/`UPDATE` (the ones that already have a real `WHERE`) as a low
"confirm before running" note; and use **allow** to suppress categories you know are
intentional (for example `drop, truncate` in a migration).

This is a **heuristic, not a SQL parser**. It splits statements on `;` and masks
comments and string/identifier literals so a `DROP` inside a `--` comment or a
`'string'` is ignored and a `;` inside a string does not split a statement — but it
does not understand stored procedures, dynamic SQL built at runtime, `MERGE`, or a
`WHERE` that is technically present yet still matches every row. Treat findings as
leads to review, not a guarantee, and always test destructive SQL inside a transaction
with a backup.

## FAQ

<details>
<summary>Does this connect to my database or run the SQL?</summary>

No. It is a purely static text scan — it never opens a connection and never executes a
statement. Everything runs locally in your browser via WebAssembly, so the SQL you
paste is never uploaded anywhere. That is exactly why it is safe to check a query you
have not decided to run.

</details>

<details>
<summary>Why is my guarded DELETE/UPDATE not flagged?</summary>

By default a `DELETE` or `UPDATE` that has a real `WHERE` clause is treated as clean,
because it targets specific rows. Turn on **strict** to also list those as a *low*
`…-CONFIRM` finding so every destructive statement gets an explicit look. A `WHERE`
that is always true — for example `WHERE 1=1`, `WHERE 'x'='x'`, or `WHERE true` — is
always flagged as *high*, because it still touches every row.

</details>

<details>
<summary>Can I get machine-readable output for CI?</summary>

Yes. Set **format** to `json` and you get a structured object with a `summary`
(counts of findings by severity and how many statements were scanned) and a `findings`
array, each entry carrying the statement number, line, severity, rule id, category,
message, and a one-line snippet. Fail your pipeline when `summary.critical` (or `high`)
is above zero.

</details>

<details>
<summary>Will it produce false positives or miss things?</summary>

Both are possible — it is a heuristic, not a full parser. It can miss destructive SQL
hidden in dynamic strings, stored procedures, or a `WHERE` clause that is present but
still matches every row, and it may flag a statement you fully intend to run. Use
**allow** to suppress categories you have reviewed (for example `drop` in a schema
migration), and always review the flagged statements yourself before executing.

</details>

## Related tools

- [SQL Linter](https://gizza.ai/tools/sql-linter/): Paste SQL to flag syntax issues plus SELECT *, comma joins, bare JOINs, and missing subquery aliases. Local, read-only linting.
- [Code Chunker](https://gizza.ai/tools/code-chunker/): Split Python, Rust, JavaScript, TypeScript, Go, Java, C/C++, C#, PHP, or Swift into line-ranged chunks that keep functions and classes intact.
- [Code Formatter](https://gizza.ai/tools/code-formatter/): Beautify and re-indent minified or messy HTML, CSS, JavaScript, or JSON. Auto-detect the language, choose spaces or tabs, and format locally in your browser.
- [CSS Autoprefixer](https://gizza.ai/tools/css-autoprefixer/): Free online CSS autoprefixer — paste CSS and add the -webkit-, -moz-, -ms-, -o- vendor prefixes browsers still need. Runs entirely in your browser.
- [Directory Tree View](https://gizza.ai/tools/directory-tree-view/): Paste a du, find, or CSV file listing and get a clean indented tree with rolled-up folder sizes and file counts. Human, SI, or raw bytes. Free, in-browser.
