@carllee1983/dbcli 1.39.2 → 1.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor/rules/dbcli.mdc +21 -12
- package/.cursor/skills/dbcli/reference.md +329 -3
- package/.cursor-plugin/plugin.json +2 -1
- package/.github/skills/dbcli/SKILL.md +21 -12
- package/.github/skills/dbcli/reference.md +329 -3
- package/CHANGELOG.md +56 -0
- package/README.zh-TW.md +1 -1
- package/assets/SKILL.md +21 -12
- package/assets/SKILL.zh-TW.md +12 -7
- package/assets/reference.md +329 -3
- package/assets/tasks/diagnose-slow-query.md +8 -0
- package/assets/tasks/mongo-safe-backfill.md +56 -0
- package/assets/tasks/mongo-schema-drift-review.md +51 -0
- package/assets/tasks/orm-drift-review.md +55 -0
- package/dist/cli.mjs +9247 -4608
- package/dist/core.d.ts +3 -0
- package/dist/core.mjs +215 -59
- package/gemini-extension.json +1 -1
- package/package.json +1 -1
- package/plugins/dbcli-agent/.codex-plugin/plugin.json +1 -1
- package/plugins/dbcli-agent/INSTALL.md +19 -10
- package/plugins/dbcli-agent/skills/dbcli/SKILL.md +21 -12
- package/plugins/dbcli-agent/skills/dbcli/reference.md +329 -3
- package/skills/dbcli/SKILL.md +21 -12
- package/skills/dbcli/reference.md +329 -3
|
@@ -105,6 +105,7 @@ dbcli schema --use prod # Scan prod DB; saves to .dbcli/schemas/prod
|
|
|
105
105
|
|
|
106
106
|
**Schema storage (v1.4+):** Schema is persisted as layered files under `.dbcli/schemas/`. With v2 multi-connection config each connection gets its own subdirectory (`.dbcli/schemas/<connection>/`). Run `dbcli schema --use <connection>` once per connection before querying it — otherwise `schema <table>` may return data from the wrong connection's cache.
|
|
107
107
|
|
|
108
|
+
> **PostgreSQL:** Introspection uses the exact `public` catalog identity throughout. Full catalog/schema/table joins prevent a reused constraint name from contaminating another table; enum lookup includes its namespace; composite primary-key order comes from the exact table OID and index ordinality; and row estimates are scoped to the exact `public` relation. Row-count SQL qualifies and quotes both `"public"` and the exact table identifier, escaping embedded quotes so mixed-case or punctuation-bearing names remain distinct and safe.
|
|
108
109
|
> **Redis:** `schema <key>` is required (no full scan). The output exposes `type`, `ttl`, `size`, and a small `sample` (e.g. first 5 hash keys). `--reset` / `--refresh` are rejected — Redis caches no schema.
|
|
109
110
|
> **Elasticsearch:** `schema [index]` flattens the `_mapping` properties (nested `a.b.c`) and emits each `.fields` multi-field as a separate column (e.g. `text` + `text.keyword`). Full scan iterates all non-system indices and stores per-connection caches alongside SQL engines.
|
|
110
111
|
> **MongoDB:** schema is sampled via `$sample` (default 100, max 1000). `--sample-method natural` switches to `find().limit()`; `random` (default) falls back to natural order on driver error. Output columns surface nested dot-paths with `presence` (0..1) and `redacted: true` flags for blacklist-matched paths. The persisted cache records `sampleMethod` and `sampleSize`; `dbcli doctor` reports them via a `sampled: method=…, size=…` line.
|
|
@@ -192,9 +193,134 @@ dbcli explain --bulk @analytics/* # glob over saved queries
|
|
|
192
193
|
| `nested-loop-large` | yellow | PG `Nested Loop` with planner rows > 10,000 |
|
|
193
194
|
|
|
194
195
|
> Notes:
|
|
195
|
-
> - `--analyze` executes the statement
|
|
196
|
+
> - `--analyze` executes the statement, so dbcli accepts it only for SQL that is
|
|
197
|
+
> structurally proven to be a read-only, function-free `SELECT` (including
|
|
198
|
+
> SELECT-only CTEs). Explicit function and table-function calls are unproven
|
|
199
|
+
> because user-defined and built-in functions may have side effects. DML, DDL,
|
|
200
|
+
> data-modifying CTEs, session assignments, function-bearing SQL, and
|
|
201
|
+
> unrecognized SQL are rejected before the adapter is invoked; use plain
|
|
202
|
+
> `dbcli explain` for those statements.
|
|
196
203
|
> - Auto-`LIMIT` is **not** applied to EXPLAIN statements (since v1.23 P1).
|
|
197
204
|
|
|
205
|
+
### lint
|
|
206
|
+
|
|
207
|
+
Static, report-only SQL anti-pattern analysis for PostgreSQL, MySQL, and
|
|
208
|
+
MariaDB. `lint` never opens a database connection, never runs the SQL, and
|
|
209
|
+
never applies a rewrite. Schema-aware findings use only the layered schema
|
|
210
|
+
cache under `.dbcli/schemas/`.
|
|
211
|
+
|
|
212
|
+
```text
|
|
213
|
+
dbcli lint [queries...]
|
|
214
|
+
dbcli lint --bulk <input>
|
|
215
|
+
dbcli --use <conn> lint [queries...]
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
An input may be inline SQL, a saved query such as `@analytics/live-summary`, a
|
|
219
|
+
SQL file such as `@queries.sql`, or a saved-query/filesystem glob such as
|
|
220
|
+
`@analytics/*` or `@queries/**/*.sql`. `--bulk` accepts a comma-separated mix
|
|
221
|
+
of those `@file`, `@glob`, and `@saved-query` inputs; quote a filesystem glob
|
|
222
|
+
in a shell so the `@` reference reaches dbcli unchanged.
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
dbcli lint "SELECT * FROM users WHERE email LIKE '%@example.com'" --format json
|
|
226
|
+
dbcli lint --bulk '@queries/**/*.sql' --format markdown
|
|
227
|
+
dbcli --use staging lint @analytics/live-summary --min-severity warn
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
| Option | Default | Meaning |
|
|
231
|
+
|---|---|---|
|
|
232
|
+
| `--format <text\|json\|markdown>` | `text` | Render one report per resolved input. |
|
|
233
|
+
| `--min-severity <info\|warn\|error>` | `info` | Omit findings below the selected severity. |
|
|
234
|
+
| `--no-schema` | off | Skip schema-only checks without reading schema-cache paths; static `NOT IN` NULL checks still run. |
|
|
235
|
+
| `--bulk <input>` | none | Resolve a comma-separated list of `@file`, `@glob`, or `@saved-query` inputs. |
|
|
236
|
+
| `--recovery` | off | On command failure, emit and save a linked `RecoveryEnvelope`. |
|
|
237
|
+
| global `--use <conn>` | configured default | Select a v2 named connection and its isolated cache; place it before `lint`: `dbcli --use <conn> lint …`. |
|
|
238
|
+
|
|
239
|
+
**Rules:**
|
|
240
|
+
|
|
241
|
+
| Rule | Severity | What it reports |
|
|
242
|
+
|---|---|---|
|
|
243
|
+
| `select-star` | warn | A top-level `SELECT *`; when one table and its cached columns are unambiguous, the finding may include a column-list rewrite draft. |
|
|
244
|
+
| `unanchored-like` | warn | A `LIKE` / `ILIKE` pattern beginning with `%`, which a conventional B-tree index cannot anchor. |
|
|
245
|
+
| `missing-limit-offset` | info | Deep pagination with `OFFSET >= 1000`; prefer keyset pagination. |
|
|
246
|
+
| `non-sargable-where` | warn | A function or arithmetic expression applied to the column side of a predicate. |
|
|
247
|
+
| `or-to-union` | info | A top-level `OR` across different columns that can complicate index selection; any UNION alternative must preserve identity and multiplicity. |
|
|
248
|
+
| `subquery-to-join` | info | `IN (SELECT …)` where an equivalent `EXISTS`, or a JOIN with proven uniqueness/deduplication, may plan better. |
|
|
249
|
+
| `distinct-groupby-abuse` | warn | Redundant `DISTINCT` when simple projected columns exactly cover the `GROUP BY` columns. |
|
|
250
|
+
| `implicit-cast` | warn | A schema-verified column/literal type mismatch that can disable index use; safe, unambiguous numeric drafts may be included. |
|
|
251
|
+
| `not-in-nullable` | warn | A right-hand `NOT IN` value that can be NULL: explicit `NULL`, outer-join null extension, a nullable subquery projection, or a known nullable CASE/cast/aggregate expression. A nullable left-hand column is not this rule. |
|
|
252
|
+
|
|
253
|
+
`implicit-cast` and the schema-enriched portion of `not-in-nullable` read the
|
|
254
|
+
selected cache through the schema loader abstraction. Static `not-in-nullable`
|
|
255
|
+
checks still run without it. All schema caches live beneath `.dbcli/schemas/`. A v2
|
|
256
|
+
configuration always uses `.dbcli/schemas/<resolved-connection>/`, including
|
|
257
|
+
the configured default. The root `.dbcli/schemas/` directory is only the
|
|
258
|
+
v1/legacy unnamed cache. Global `dbcli --use <conn> lint …` selects another
|
|
259
|
+
named v2 slot. The command never refreshes the cache and never falls back to
|
|
260
|
+
schema embedded in config.
|
|
261
|
+
|
|
262
|
+
Skipped rules are returned with machine-readable `blocked:` reasons:
|
|
263
|
+
|
|
264
|
+
- Invalid SQL blocks all nine rules with `blocked: parse failed` and includes
|
|
265
|
+
`parseError`.
|
|
266
|
+
- `--no-schema` blocks `implicit-cast` and the schema-dependent portion of
|
|
267
|
+
`not-in-nullable` with `blocked: --no-schema`; static RHS hazards still run.
|
|
268
|
+
- A missing layered cache records
|
|
269
|
+
`blocked: schema cache unavailable (run dbcli schema)` for those unavailable
|
|
270
|
+
schema checks while retaining static RHS findings.
|
|
271
|
+
|
|
272
|
+
Every finding includes its rule, severity, source span, message, and
|
|
273
|
+
`schemaVerified` state. Some findings also carry a confidence-labelled rewrite
|
|
274
|
+
draft and a shell-safe verification command. It uses
|
|
275
|
+
`dbcli explain --analyze` only when the statement is structurally proven read-only;
|
|
276
|
+
function-bearing and session-assignment statements are unproven, so lint
|
|
277
|
+
falls back to plain `dbcli explain`. These are suggestions only: `lint` neither
|
|
278
|
+
executes the verification command nor changes the query.
|
|
279
|
+
|
|
280
|
+
When schema identifiers collide after case folding, schema-aware findings and
|
|
281
|
+
rewrites are withheld. The SQL parser does not preserve reliable quote
|
|
282
|
+
provenance, so an exact-looking mixed-case AST identifier cannot disambiguate
|
|
283
|
+
that collision. CTE, derived, schema-qualified, and database-qualified
|
|
284
|
+
relations also never borrow facts from the unqualified cache.
|
|
285
|
+
|
|
286
|
+
For `not-in-nullable`, remove or filter right-hand NULL values. In a subquery,
|
|
287
|
+
filter the projected value with `IS NOT NULL`; `NOT EXISTS` may be a better
|
|
288
|
+
semantic form when appropriate. dbcli does not automatically rewrite this case
|
|
289
|
+
unless correlation, type classification, qualified-column resolution, and the
|
|
290
|
+
rewrite target are all unambiguous. A direct or `AND`-conjoined `IS NOT NULL`
|
|
291
|
+
filter on the exact projected expression suppresses the finding; aggregates
|
|
292
|
+
apply the same proof in `HAVING`. Filters under `OR` or ambiguous expression
|
|
293
|
+
matches do not. The rule recursively checks projection, JOIN `ON`, `WHERE`, and
|
|
294
|
+
`HAVING` expressions, using each nested SELECT/CTE/derived statement's own
|
|
295
|
+
scope. Qualified outer-join null extension remains detectable without a cache,
|
|
296
|
+
but a join's synthetic NULL row is not applied inside that join's own `ON`;
|
|
297
|
+
declared nullability and completed earlier joins still apply there.
|
|
298
|
+
|
|
299
|
+
Trimmed JSON example:
|
|
300
|
+
|
|
301
|
+
```json
|
|
302
|
+
[
|
|
303
|
+
{
|
|
304
|
+
"sql": "SELECT * FROM users",
|
|
305
|
+
"dialect": "postgresql",
|
|
306
|
+
"findings": [
|
|
307
|
+
{
|
|
308
|
+
"rule": "select-star",
|
|
309
|
+
"severity": "warn",
|
|
310
|
+
"message": "SELECT * fetches every column; list the columns you need.",
|
|
311
|
+
"span": { "start": 0, "end": 8 },
|
|
312
|
+
"schemaVerified": false
|
|
313
|
+
}
|
|
314
|
+
],
|
|
315
|
+
"skippedRules": [],
|
|
316
|
+
"relatedCommands": [
|
|
317
|
+
"dbcli guide missing-index-for \"SELECT * FROM users\"",
|
|
318
|
+
"dbcli explain --analyze \"SELECT * FROM users\""
|
|
319
|
+
]
|
|
320
|
+
}
|
|
321
|
+
]
|
|
322
|
+
```
|
|
323
|
+
|
|
198
324
|
### plan
|
|
199
325
|
|
|
200
326
|
Static SQL risk analyzer. Classifies a statement into the same permission tiers
|
|
@@ -583,6 +709,202 @@ dbcli diff --against before.json --format json
|
|
|
583
709
|
**Options:** `--snapshot <path>`, `--against <path>`, `--format <json|table>`
|
|
584
710
|
**Permission:** query-only+
|
|
585
711
|
|
|
712
|
+
#### `diff --against-orm`
|
|
713
|
+
|
|
714
|
+
Compare an ORM definition with the local SQL schema cache. This mode reads
|
|
715
|
+
`config.schema`; it does not open a database connection, refresh the cache, or
|
|
716
|
+
execute a proposal. An empty cache fails with
|
|
717
|
+
`Schema cache is empty. Run 'dbcli schema' first.` Snapshot mode remains a
|
|
718
|
+
separate `--snapshot` / `--against` workflow.
|
|
719
|
+
|
|
720
|
+
```bash
|
|
721
|
+
# Prisma and normalized JSON accept exactly one file
|
|
722
|
+
dbcli diff --against-orm prisma/schema.prisma --format json
|
|
723
|
+
dbcli diff --against-orm schema.normalized.json --orm-format json --format table
|
|
724
|
+
|
|
725
|
+
# Drizzle requires a PostgreSQL drizzle-kit v7 snapshot (generate it first)
|
|
726
|
+
drizzle-kit generate
|
|
727
|
+
dbcli diff --against-orm drizzle/meta/0001_snapshot.json --orm-format drizzle --format table
|
|
728
|
+
|
|
729
|
+
# DDL accepts repeatable or comma-separated paths and real filesystem globs
|
|
730
|
+
dbcli diff --against-orm "migrations/*.sql" --format markdown
|
|
731
|
+
dbcli diff --against-orm migrations/base.sql,migrations/accounts.sql \
|
|
732
|
+
--against-orm migrations/orders.sql --orm-format ddl --format json
|
|
733
|
+
|
|
734
|
+
# Ignore patterns are comma-separated and match qualified table identity
|
|
735
|
+
dbcli diff --against-orm prisma/schema.prisma --ignore 'public.audit_*,public.Legacy'
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
##### TypeORM
|
|
739
|
+
|
|
740
|
+
TypeORM entities are not parsed directly. `schema:log` prints the SQL that
|
|
741
|
+
`schema:sync` would execute without applying it; `-d` is the required data-source
|
|
742
|
+
path. Generate that DDL, then select the `typeorm` alias so the report is tagged
|
|
743
|
+
`ormSource: typeorm`:
|
|
744
|
+
|
|
745
|
+
```bash
|
|
746
|
+
bunx typeorm schema:log -d <path/to/datasource> > schema.sql
|
|
747
|
+
dbcli diff --against-orm schema.sql --orm-format typeorm --format table
|
|
748
|
+
```
|
|
749
|
+
|
|
750
|
+
With `--orm-format typeorm`, `typeorm_metadata` and `migrations` are
|
|
751
|
+
default-ignored and appear as `unmanaged` rather than scored drift. Passing a
|
|
752
|
+
TypeORM `.ts`, `.js`, `.mjs`, or `.cjs` source file is rejected with the
|
|
753
|
+
`schema:log` command to run. See the
|
|
754
|
+
[TypeORM CLI documentation](https://typeorm.io/docs/using-cli) and
|
|
755
|
+
[`SchemaLogCommand`](https://github.com/typeorm/typeorm/blob/master/src/commands/SchemaLogCommand.ts).
|
|
756
|
+
|
|
757
|
+
##### Sequelize
|
|
758
|
+
|
|
759
|
+
Sequelize CLI does not provide a universal `db:migrate --dry-run`. Point the
|
|
760
|
+
project's existing Sequelize configuration at an empty scratch database, apply
|
|
761
|
+
the migrations there, and dump definitions without row data:
|
|
762
|
+
|
|
763
|
+
```bash
|
|
764
|
+
# Configure Sequelize for an empty scratch database first
|
|
765
|
+
bunx sequelize-cli db:migrate
|
|
766
|
+
|
|
767
|
+
# PostgreSQL scratch database
|
|
768
|
+
pg_dump --schema-only <scratch-database> > schema.sql
|
|
769
|
+
|
|
770
|
+
# MySQL scratch database
|
|
771
|
+
mysqldump --no-data <database> > schema.sql
|
|
772
|
+
|
|
773
|
+
dbcli diff --against-orm schema.sql --orm-format sequelize --format json
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
With `--orm-format sequelize`, `SequelizeMeta` is default-ignored and appears as
|
|
777
|
+
`unmanaged` rather than scored drift. Passing a Sequelize `.ts`, `.js`, `.mjs`,
|
|
778
|
+
or `.cjs` model file is rejected with the scratch-database and schema-only dump
|
|
779
|
+
recipe. See the
|
|
780
|
+
[Sequelize CLI migration command](https://github.com/sequelize/cli/blob/main/src/commands/migrate.js),
|
|
781
|
+
[PostgreSQL `pg_dump`](https://www.postgresql.org/docs/current/app-pgdump.html),
|
|
782
|
+
and [MySQL `mysqldump`](https://dev.mysql.com/doc/refman/8.4/en/mysqldump-definition-data-dumps.html)
|
|
783
|
+
references.
|
|
784
|
+
|
|
785
|
+
| Option | Behavior |
|
|
786
|
+
| :--- | :--- |
|
|
787
|
+
| `--against-orm <paths>` | Repeatable or comma-separated input. DDL-family inputs (raw DDL, TypeORM, and Sequelize) support real filesystem globs; matches are deduplicated and put in deterministic path order, then parsed as one shared ordered context so an index in a later file can attach to a table declared in an earlier file. Prisma, normalized JSON, and Drizzle accept exactly one file, and globs are rejected for those formats. |
|
|
788
|
+
| Drizzle input | Run `drizzle-kit generate`, then pass the PostgreSQL drizzle-kit v7 snapshot at `drizzle/meta/<NNNN>_snapshot.json`. TypeScript ORM schema sources (`.ts` or `.TS`) are rejected with that snapshot-generation hint; dbcli does not parse them directly. |
|
|
789
|
+
| TypeORM / Sequelize input | Generate DDL with the ORM/database tooling, then pass the SQL file with the matching `typeorm` or `sequelize` alias. Entity/model source files are rejected rather than parsed. |
|
|
790
|
+
| `--orm-format prisma\|ddl\|json\|drizzle\|typeorm\|sequelize` | Override extension/content detection. The `typeorm` and `sequelize` aliases use the DDL adapter while preserving the source tag and ORM-specific default ignores. Without an override, dbcli detects Prisma, raw DDL, normalized JSON, or a Drizzle snapshot from the path and content. |
|
|
791
|
+
| `--ignore <globs>` | Comma-separated, case-sensitive table globs. Patterns match the qualified display identity (for example `public.Users`). `_prisma_migrations` is always unmanaged; the TypeORM alias additionally ignores `typeorm_metadata` and `migrations`, and the Sequelize alias additionally ignores `SequelizeMeta`. |
|
|
792
|
+
| `--format json\|table\|markdown` | Select machine JSON, human table, or Markdown output. Markdown is available only in ORM drift mode. |
|
|
793
|
+
| `--recovery` | On an I/O, configuration, empty-cache, invalid-format, or unsupported-engine failure, emit and save a structured recovery envelope. Invalid Prisma/DDL constructs normally become `unparsed` entries instead of throwing. |
|
|
794
|
+
|
|
795
|
+
The command supports PostgreSQL, MySQL, and MariaDB configurations. Only
|
|
796
|
+
error-level **scored drift** determines the report's drift exit code: one or more
|
|
797
|
+
scored errors exits `1`; warnings, infos, `unmanaged`, or `unparsed` entries alone
|
|
798
|
+
exit `0`. Command/configuration failures independently exit code `1`. The four
|
|
799
|
+
drift categories and tolerance rules are:
|
|
800
|
+
|
|
801
|
+
| Category | Severity and comparison rule |
|
|
802
|
+
| :--- | :--- |
|
|
803
|
+
| `missing_in_db` | `error` — a table, column, or index exists in the ORM definition but not in the cached DB schema. |
|
|
804
|
+
| `missing_in_orm` | `warn` — a table, column, or index exists in the cached DB schema but not in the ORM definition. |
|
|
805
|
+
| `mismatch` | `error` when the type family or nullability differs; `info` for same-family type spelling, default, or primary-key differences. |
|
|
806
|
+
| `unmanaged` | `info`, excluded from error/warn scoring — the table matched the built-in or user `--ignore` patterns. |
|
|
807
|
+
|
|
808
|
+
Type-family tolerance deliberately treats engine spellings such as `text` and
|
|
809
|
+
`varchar(191)` as the same family: the spelling difference is still visible as
|
|
810
|
+
`info`, while an integer/text family difference is an `error`. Indexes compare
|
|
811
|
+
by structural index signatures — ordered, case-folded column names plus
|
|
812
|
+
uniqueness — rather than by engine-specific index names. Duplicate signatures
|
|
813
|
+
are emitted once. Drift entries sort deterministically by table, object, category,
|
|
814
|
+
and detail using Unicode code-point order, never locale-dependent collation.
|
|
815
|
+
|
|
816
|
+
**Schema and table identity.** Storage preserves exact, case-sensitive schema
|
|
817
|
+
and table names from the database catalog. Exact, case-sensitive `(schema, table)`
|
|
818
|
+
tuples are the comparison key, so PostgreSQL `users` and `"Users"` can coexist.
|
|
819
|
+
DDL resolution rules: unquoted SQL identifiers fold to lowercase; quoted identifiers match exactly.
|
|
820
|
+
For example, unquoted `Users` resolves to `users`, and quoted
|
|
821
|
+
`"Users"` resolves only to `Users`. Quote state comes from the parsed identifier representation;
|
|
822
|
+
dbcli never infers it from display text, catalog spelling, or a
|
|
823
|
+
Prisma mapping. Qualified components resolve independently, and unqualified ORM
|
|
824
|
+
identities use the cached DB default schema when one is known. Qualified display
|
|
825
|
+
names and `--ignore` matching remain case-sensitive. Duplicate exact or
|
|
826
|
+
duplicate resolved table identities fail closed instead of overwriting one
|
|
827
|
+
another.
|
|
828
|
+
|
|
829
|
+
**Prisma subset.** The parser supports `model` blocks; scalar `String`, `Int`,
|
|
830
|
+
`BigInt`, `Float`, `Decimal`, `Boolean`, `DateTime`, `Json`, and `Bytes` fields;
|
|
831
|
+
`?`; relation-side `[]`; `@id`, `@unique`, `@default(...)`, `@map("...")`,
|
|
832
|
+
`@@map("...")`, `@@index([...])`, `@@unique([...])`; relations with
|
|
833
|
+
`fields` / `references`; and the validated native mappings `@db.Text`,
|
|
834
|
+
`@db.VarChar(n)`, `@db.Uuid`, `@db.Timestamptz([precision])`, `@db.Date`,
|
|
835
|
+
`@db.SmallInt`, and `@db.JsonB`. Views, composite types, enums used as scalar
|
|
836
|
+
columns, multi-schema datasource configuration, malformed declarations, unknown
|
|
837
|
+
attributes, and unsupported native mappings are never guessed.
|
|
838
|
+
|
|
839
|
+
Prisma, DDL, and Drizzle constructs outside the supported subset are retained in
|
|
840
|
+
`unparsed` with a `blocked:` reason. These entries are separate from scored drift:
|
|
841
|
+
inspect and resolve them before treating an otherwise clean summary as complete.
|
|
842
|
+
Drizzle enums and other unsupported snapshot constructs therefore appear as blocked
|
|
843
|
+
`unparsed` entries rather than managed tables or columns.
|
|
844
|
+
Multi-file DDL is consumed as one deterministic shared ordered statement context,
|
|
845
|
+
so later `CREATE INDEX` statements can reference tables declared in earlier
|
|
846
|
+
files. PostgreSQL `PARTITION BY` and MySQL/MariaDB table engine, charset, and
|
|
847
|
+
other `CREATE TABLE` table options are unsupported: the construct produces a
|
|
848
|
+
`blocked:` `unparsed` entry and does not emit a managed ORM table.
|
|
849
|
+
The normalized JSON escape hatch is Zod-validated and uses an array of tables
|
|
850
|
+
with explicit exact `identity` objects; optional parsed identifiers must include
|
|
851
|
+
their `quoted` flags, and every normalized JSON `unparsed.reason` must start with
|
|
852
|
+
`blocked:`.
|
|
853
|
+
|
|
854
|
+
```json
|
|
855
|
+
{
|
|
856
|
+
"ormSource": "prisma",
|
|
857
|
+
"entries": [
|
|
858
|
+
{
|
|
859
|
+
"category": "missing_in_db",
|
|
860
|
+
"severity": "error",
|
|
861
|
+
"table": "public.users",
|
|
862
|
+
"object": "email",
|
|
863
|
+
"detail": "column 'email' (text) is defined in prisma but absent in the database",
|
|
864
|
+
"proposedCommands": [
|
|
865
|
+
"# escalate: schema-qualified table 'public.users' is not losslessly representable by dbcli migrate — run: dbcli skill tasks plan migration-review"
|
|
866
|
+
]
|
|
867
|
+
}
|
|
868
|
+
],
|
|
869
|
+
"unparsed": [],
|
|
870
|
+
"summary": { "errors": 1, "warns": 0, "infos": 0, "unmanaged": 0 }
|
|
871
|
+
}
|
|
872
|
+
```
|
|
873
|
+
|
|
874
|
+
Missing unqualified columns and indexes may receive shell-safe, dry-run-by-default
|
|
875
|
+
`dbcli migrate add-column` or `add-index` proposal strings. Simple arguments stay
|
|
876
|
+
unquoted; unsafe shell characters are POSIX single-quoted. Table creation,
|
|
877
|
+
removal, mismatch, and DB-only drift escalate to `migration-review`. A
|
|
878
|
+
schema-qualified target, or index columns that the current `migrate --columns`
|
|
879
|
+
CLI cannot represent losslessly, also escalates instead of emitting a corrupt
|
|
880
|
+
command. Any table, column, or type positional beginning with `-` also escalates
|
|
881
|
+
so Commander cannot reinterpret it as an option. A leading-dash option value is
|
|
882
|
+
rendered with option-safe attached syntax, for example `--default=-1` or
|
|
883
|
+
`--columns=--config,email`. Proposals are text only and never add `--execute`.
|
|
884
|
+
|
|
885
|
+
For a guided, cache-refreshing review, use the built-in `orm-drift-review` pack:
|
|
886
|
+
|
|
887
|
+
```bash
|
|
888
|
+
dbcli skill tasks plan orm-drift-review \
|
|
889
|
+
--param orm_path=prisma/schema.prisma \
|
|
890
|
+
--format json
|
|
891
|
+
```
|
|
892
|
+
|
|
893
|
+
The plan is `blacklist list` → `schema --format json` →
|
|
894
|
+
`diff --against-orm ... --format json`. Run any proposed `migrate` command in its
|
|
895
|
+
default dry-run mode, capture the emitted DDL, confirm its exact target, and pass
|
|
896
|
+
both values to the separate migration review:
|
|
897
|
+
|
|
898
|
+
```sh
|
|
899
|
+
dbcli skill tasks plan migration-review \
|
|
900
|
+
--param "table=${exact_table}" \
|
|
901
|
+
--param "ddl=${captured_ddl}"
|
|
902
|
+
```
|
|
903
|
+
|
|
904
|
+
Both parameters are required. Keep each expansion as one quoted shell argument;
|
|
905
|
+
never use `eval`, and consider `--execute` only after the plan and captured DDL
|
|
906
|
+
have been reviewed.
|
|
907
|
+
|
|
586
908
|
### snapshot
|
|
587
909
|
|
|
588
910
|
Capture a **result fingerprint** of a query (not schema): `rowCount` plus per-column
|
|
@@ -1713,8 +2035,12 @@ a read-only (`plan-only`) pack taking a required `table` parameter that walks
|
|
|
1713
2035
|
in recent audit activity. Additional read-only packs ship for common agent
|
|
1714
2036
|
workflows: `audit-permissions` (permission/blacklist audit), `safe-backfill`
|
|
1715
2037
|
(plan a write with blacklist+schema+risk checks), `schema-drift-review` (cached
|
|
1716
|
-
vs live schema diff),
|
|
1717
|
-
|
|
2038
|
+
vs live schema diff), `orm-drift-review` (ORM definition vs cached DB schema),
|
|
2039
|
+
and `connection-health` (reachability/config/capacity
|
|
2040
|
+
triage). **MongoDB packs:** `mongo-safe-backfill` (dry-run–previewed backfill)
|
|
2041
|
+
and `mongo-schema-drift-review` (sampled dot-path drift, with a `sample_size` knob
|
|
2042
|
+
to damp sampling noise); filter them with `dbcli skill tasks list --engine mongodb`.
|
|
2043
|
+
Run `dbcli skill tasks list` for the full set.
|
|
1718
2044
|
|
|
1719
2045
|
```bash
|
|
1720
2046
|
dbcli skill tasks plan analyze-table-perf --param table=betting_logs --format json
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,62 @@ All notable changes to dbcli are documented here.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.42.0] - 2026-07-20 - Drizzle Snapshot 與 ORM DDL 工作流擴充
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Drizzle Kit snapshot 可直接用於 ORM drift 比對。** `dbcli diff --against-orm` 新增 Drizzle snapshot 格式偵測與 `NormalizedSchema` adapter,支援 PostgreSQL v7 snapshot 的 table、column、primary key、unique constraint、index 與 foreign key metadata。
|
|
13
|
+
- **TypeORM/Sequelize DDL alias。** `--orm-format typeorm`、`typeorm-ddl`、`sequelize` 與 `sequelize-ddl` 可直接走既有 DDL adapter;自動忽略 `typeorm_metadata` 與 `SequelizeMeta` bookkeeping table,並補上 source-file 使用者的可執行匯出/比對指引。
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- **ORM drift 文件完整同步。** 英文/繁體中文的 Markdown 與 HTML 使用者文件、skill assets、各平台 plugin 副本及 reference 已補上 Drizzle snapshot、TypeORM/Sequelize DDL 的格式、限制與操作範例。
|
|
18
|
+
- **跨平台發版 metadata 對齊。** npm package、Codex/Claude/Cursor plugin、packaged Codex plugin 與 Gemini extension 統一為 `1.42.0`。
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- **不支援的 ORM 輸入改為 fail closed。** Drizzle snapshot 會拒絕不支援的版本/dialect、generated/identity/enum/composite primary key 等結構,以及無法無損轉換的 column default;TypeORM/Sequelize source file 則回報完整的匯出 DDL recipe,不再被 JSON/DDL fallback 誤解析。
|
|
23
|
+
- **Qualified ignore identity 保留完整。** ORM drift 的 ignore 比對不再把 schema-qualified identity 降成 bare table name,避免同名 table 跨 schema 時被錯誤忽略;ORM DDL alias 也會正確沿用 DDL 輸入處理與 bookkeeping ignore。
|
|
24
|
+
|
|
25
|
+
## [1.41.0] - 2026-07-19 - ORM Drift 比對與無損 Schema Identity
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- **`dbcli diff --against-orm` ORM drift 比對。** 可將 Prisma schema、DDL/migration SQL 或 normalized JSON 與既有 SQL schema cache 比對;支援多檔 DDL、filesystem glob、格式自動偵測、大小寫敏感的 `--ignore` pattern,以及 JSON、table、Markdown 輸出。比對只讀本地 cache,不連線、不更新 cache,也不執行提案。
|
|
30
|
+
- **結構化 drift 分類與安全提案。** 報告區分 `missing_in_db`、`missing_in_orm`、`mismatch`、`unmanaged` 與 `unparsed`;只有計分後的 error 會使 drift exit code 為 `1`。可無損表達的缺漏欄位/index 會產生 shell-safe、預設 dry-run 的 `migrate` 提案,其餘情況升級至 `migration-review`。
|
|
31
|
+
- **`orm-drift-review` agent task pack。** 工作流依序執行 blacklist 檢查、schema cache 更新與 ORM drift JSON 比對,並要求將 dry-run DDL 與精確目標交給獨立 migration review。
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
|
|
35
|
+
- **Schema identity 改為精確保存。** PostgreSQL schema/table 名稱不再正規化為小寫;quoted 與 unquoted identifier 依 SQL 規則解析,qualified name、ignore pattern、foreign key 與 drift output 都保留大小寫與 schema identity。
|
|
36
|
+
- **ORM drift 文件完整同步。** 英文/繁體中文的 Markdown 與 HTML 使用者文件、skill assets、各平台 plugin 副本及 reference 已補上格式、exit code、安全邊界與操作流程。
|
|
37
|
+
- **跨平台發版 metadata 對齊。** npm package、Codex/Claude/Cursor plugin、packaged Codex plugin 與 Gemini extension 統一為 `1.41.0`。
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- **Lossy ORM drift proposal 改為 fail closed。** Schema-qualified target、dash-leading positional、無法無損表達的 index column、identity collision 與不支援語法不再輸出可能損壞的指令,而是阻擋或升級人工審查。
|
|
42
|
+
- **DDL/Prisma adapter identity 與語意硬化。** 多檔 DDL 共用 deterministic context,foreign key pairing、default schema resolution、table option/partition 阻擋、重複 index 去重與 Unicode code-point 穩定排序皆保留來源語意。
|
|
43
|
+
|
|
44
|
+
## [1.40.0] - 2026-07-19 - SQL Lint、安全強化與 Agent 工作流擴充
|
|
45
|
+
|
|
46
|
+
### Added
|
|
47
|
+
|
|
48
|
+
- **新增唯讀 `dbcli lint` 靜態 SQL 顧問。** 支援 inline SQL、saved query、SQL 檔案與 glob/混合批次輸入,提供 text、JSON、Markdown 輸出、最低嚴重度篩選、`--no-schema` 與 `--recovery`;指令不連線、不執行 SQL,也不會自動套用 rewrite。
|
|
49
|
+
- **九條結構與 schema-aware lint 規則。** 涵蓋 `SELECT *`、未錨定 `LIKE`、深度 `OFFSET`、non-sargable predicate、`OR`/subquery 改寫機會、重複 `DISTINCT` + `GROUP BY`、implicit cast,以及 `NOT IN` 右側 NULL 風險;finding 可附 confidence 標籤的草稿與 shell-safe 驗證指令。
|
|
50
|
+
- **MongoDB agent task packs。** 新增 `mongo-safe-backfill` 與 `mongo-schema-drift-review`,補上 MongoDB 安全回填與 schema drift 檢視工作流。
|
|
51
|
+
|
|
52
|
+
### Changed
|
|
53
|
+
|
|
54
|
+
- **Slow-query guide 納入 lint。** `guide slow-query` 現在會先安排本機靜態分析,再銜接 explain 與診斷 snippets,brief plan 也保留執行 metadata。
|
|
55
|
+
- **Agent 與使用者文件完整同步。** `lint` 已寫入 skill assets、platform plugin 副本及英文/繁體中文 Markdown 與 HTML 文件;GitHub Pages 產品介紹頁同步完成雙語、可及性與行動裝置導覽重構。
|
|
56
|
+
- **跨平台發版 metadata 對齊。** npm package、Codex/Claude/Cursor plugin、packaged Codex plugin 與 Gemini extension 統一為 `1.40.0`。
|
|
57
|
+
|
|
58
|
+
### Fixed
|
|
59
|
+
|
|
60
|
+
- **Lint 採 fail-closed 安全邊界。** 解析失敗、schema binding 不明、identifier 大小寫碰撞、CTE/derived/qualified relation 與不安全 rewrite proof 會阻擋對應建議,不再借用不可靠的 cache facts。
|
|
61
|
+
- **`NOT IN` NULL 分析補齊 scope 與 provenance。** 遞迴處理巢狀 SELECT、CTE、derived statement、JOIN `ON`、`WHERE`、`HAVING`、outer-join null extension、nullable 投影與 CASE/cast/aggregate,並保留正確 traversal order。
|
|
62
|
+
- **Lint audit/recovery 遮蔽與驗證指令硬化。** positional、global、bulk 與 `--` 後的 SQL 都會遮蔽;只有結構上已證明唯讀的 SQL 才建議 `explain --analyze`,session assignment 與 function-bearing statement 會保守退回 plain explain。
|
|
63
|
+
|
|
8
64
|
## [1.39.2] - 2026-07-03 - Windows 跨平台、skill 安裝安全與 plugin 版本對齊
|
|
9
65
|
|
|
10
66
|
> npm `1.39.1` 已於 2026-06-30 發布;本批修復在其後累積於同一版號下(npm 版本不可覆蓋),故獨立為 1.39.2 以便日後發布。
|
package/README.zh-TW.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
統一的資料庫 CLI 工具,讓 AI 代理(Claude Code、Gemini、Copilot、Cursor)能安全地查詢、探索與操作資料庫。
|
|
6
6
|
|
|
7
|
-
**核心價值:** AI 代理可透過單一、具權限控管的 CLI
|
|
7
|
+
**核心價值:** AI 代理可透過單一、具權限控管的 CLI 工具,在敏感資料保護下安全存取專案資料庫。
|
|
8
8
|
|
|
9
9
|
> **安全性更新:** `dbcli init` 現在只會在 `./.dbcli/config.json` 寫入一個很小的專案綁定 stub。完整的連線設定會存放在 `~/.config/dbcli/projects/<project-id>/config.json`,因此敏感設定預設不會留在專案工作區內。
|
|
10
10
|
|
package/assets/SKILL.md
CHANGED
|
@@ -45,7 +45,7 @@ takes a full JSON filter and is exempt.)
|
|
|
45
45
|
|
|
46
46
|
Slow-query diagnosis has three canonical paths (pick by what you already know):
|
|
47
47
|
|
|
48
|
-
- Known slow SQL → `skill tasks plan diagnose-slow-query --param query="<SQL>"` → `guide missing-index-for "<SQL>"`
|
|
48
|
+
- Known slow SQL → `skill tasks plan diagnose-slow-query --param query="<SQL>"` → `lint "<SQL>"` → `guide missing-index-for "<SQL>"`
|
|
49
49
|
- Known hot table → `skill tasks plan analyze-table-perf --param table=<table>`
|
|
50
50
|
- Whole-environment scan → `report --section perf` → `guide slow-query`
|
|
51
51
|
|
|
@@ -54,7 +54,7 @@ afterwards add only the `@diag/*` it does not cover (`missing-indexes`, `locks`,
|
|
|
54
54
|
`table-sizes`). Once you have a specific slow statement, `explain --analyze "<SQL>"` shows its plan.
|
|
55
55
|
|
|
56
56
|
**On failure:** pass `--recovery` to `query` / `q` / `insert` / `update` / `delete` /
|
|
57
|
-
`export` / `schema` / `inspect`. The command emits a `RecoveryEnvelope` to stdout and saves
|
|
57
|
+
`export` / `schema` / `inspect` / `lint` / `diff --against-orm`. The command emits a `RecoveryEnvelope` to stdout and saves
|
|
58
58
|
it to `.dbcli/last-recovery.json`; then `dbcli recover` inspects it and `dbcli recover --apply`
|
|
59
59
|
runs the saved plan under risk gating. Multi-turn `--next`, connection branching, and the
|
|
60
60
|
post-apply verify probe are documented in reference.md §Recovery Cookbook.
|
|
@@ -81,12 +81,16 @@ The plan is an ordered list of dbcli commands with rationale and risk labels. Ex
|
|
|
81
81
|
one at a time — task plans do **not** override blacklist, schema, dry-run, or confirmation
|
|
82
82
|
requirements.
|
|
83
83
|
|
|
84
|
-
Builtin packs: `diagnose-slow-query` (targets a specific SQL),
|
|
85
|
-
a specific table; `dbcli inspect` auto-suggests it for the
|
|
86
|
-
activity), `audit-permissions`, `safe-backfill`,
|
|
87
|
-
|
|
88
|
-
`
|
|
89
|
-
|
|
84
|
+
Builtin packs (SQL — postgres/mysql): `diagnose-slow-query` (targets a specific SQL),
|
|
85
|
+
`analyze-table-perf` (targets a specific table; `dbcli inspect` auto-suggests it for the
|
|
86
|
+
hottest table in recent audit activity), `audit-permissions`, `safe-backfill`,
|
|
87
|
+
`schema-drift-review`, `orm-drift-review` (ORM definition vs cached DB schema),
|
|
88
|
+
`connection-health`. Review/verify packs: `pr-database-review`,
|
|
89
|
+
`migration-review`, `safe-backfill-verify`, `slow-endpoint-investigation`. MongoDB packs:
|
|
90
|
+
`mongo-safe-backfill` (dry-run–previewed backfill), `mongo-schema-drift-review` (sampled
|
|
91
|
+
dot-path drift). All are read-only `plan-only` — pick the pack matching the situation, and
|
|
92
|
+
run any index/DDL proposal through `migration-review` before writing. Redis/Elasticsearch
|
|
93
|
+
have no packs yet — lead with `guide` / `report` there.
|
|
90
94
|
|
|
91
95
|
Tasks live under `assets/tasks/` (builtin), `.dbcli-shared/tasks/` (shared), and
|
|
92
96
|
`.dbcli/tasks/` (local override).
|
|
@@ -101,9 +105,9 @@ in **How to use dbcli** still applies.
|
|
|
101
105
|
| DB-backed feature | `blacklist list` → `schema <object>` → `queries suggest <intent>` |
|
|
102
106
|
| DB report / dashboard request | `blacklist list` → `queries search <keywords>` / `queries suggest <intent>` → `queries show @<name>` → `q @<name> --ui` or `--format html` |
|
|
103
107
|
| Application data bug | `audit tail --for-agent --n 10` → `blacklist list` → `schema <object>` → narrow query |
|
|
104
|
-
| ORM or migration work | `schema --format json` → `diff --
|
|
108
|
+
| ORM or migration work | `schema --format json` → `diff --against-orm <orm-schema>` → review error-level drift → proposals via `migrate` (dry-run) → `migration-review` task pack → `diff --against <snapshot>` after applying. |
|
|
105
109
|
| PR database review | Review changed persistence paths, then propose concrete `schema` / `plan` / `dry-run` / `report` / `guide` commands per material claim. |
|
|
106
|
-
| Slow endpoint or query | `report --section perf` → task pack `analyze-table-perf` → `guide missing-index-for "<query>"`; use `proxy analyze` when logs exist. |
|
|
110
|
+
| Slow endpoint or query | `report --section perf` → task pack `analyze-table-perf` → `lint "<query>"` → `guide missing-index-for "<query>"`; use `proxy analyze` when logs exist. |
|
|
107
111
|
| Safe data backfill | `blacklist list` → `schema <object>` → count/scope query → `update … --dry-run` → read-back or snippet `--verify`. |
|
|
108
112
|
| Environment validation | `status --format json` → `doctor --format json` → `inspect --for-agent --no-connect`. |
|
|
109
113
|
|
|
@@ -121,9 +125,13 @@ dbcli q @<name> --param k=v --format html > report.html
|
|
|
121
125
|
dbcli export "<SQL>" --format html --output report.html
|
|
122
126
|
dbcli audit tail --for-agent --n 10
|
|
123
127
|
dbcli diff --snapshot <name>
|
|
128
|
+
dbcli diff --against-orm prisma/schema.prisma --format json
|
|
129
|
+
dbcli diff --against-orm "migrations/*.sql" --format markdown
|
|
130
|
+
dbcli skill tasks plan orm-drift-review --param orm_path=prisma/schema.prisma --format json
|
|
124
131
|
dbcli report --section perf --format json
|
|
125
132
|
dbcli skill tasks plan analyze-table-perf --param table=<table> --format json
|
|
126
133
|
dbcli guide missing-index-for "<query>" --format json
|
|
134
|
+
dbcli lint "<SQL>" --format json
|
|
127
135
|
dbcli update <object> --where "<bounded predicate>" --set '<json>' --dry-run --format json
|
|
128
136
|
dbcli inspect --for-agent --no-connect --format json
|
|
129
137
|
```
|
|
@@ -290,6 +298,7 @@ Full flags and edge cases: see [reference.md](reference.md) `init` section.
|
|
|
290
298
|
| `schema` | query-only+ | SQL: per-table or full scan into `.dbcli/schemas/`. MongoDB: sampled. ES: flattened mapping. Redis: per-key only (type/TTL/size). Supports `--recovery`. |
|
|
291
299
|
| `query` | query-only+ | SQL, Mongo JSON (`--collection`), Redis command, or ES DSL/Lucene (`--collection`). `--format table\|json\|csv\|html`, `--ui` to open the interactive dashboard in a browser. Supports `--recovery`. |
|
|
292
300
|
| `explain` | query-only+ | **(v1.23)** Read-only query plan with annotations. SQL only. Single query, `@saved-query`, `@file.sql`, or `--bulk @glob/*`. `--analyze` (EXPLAIN ANALYZE / MariaDB ANALYZE SELECT), `--format markdown\|json\|table`. |
|
|
301
|
+
| `lint` | n/a | Static SQL anti-pattern advisor (no DB connection). 9 rules incl. schema-aware implicit-cast / NOT IN-nullable checks via the layered `.dbcli/schemas/` cache; global `--use <conn>` selects a named cache. Findings carry rewrite drafts + guarded `explain` verify commands (`--analyze` only for proven read-only SQL) — report-only, never executes. `--format text\|json\|markdown`, `--min-severity`, `--no-schema`, `--bulk`. Supports `--recovery`. |
|
|
293
302
|
| `plan` | n/a | Static SQL risk analyzer (`--format text\|json`); classifies a statement without connecting to the database. |
|
|
294
303
|
| `q` | query-only+ | Run a saved snippet by `@name` with `--param k=v`. Supports `--verify` to run assertions. |
|
|
295
304
|
| `queries` | n/a | Manage saved snippets: `list` / `show` / `search` / `suggest` / `new` / `edit` / `check` / `delete` / `rename` / `copy` / `import` / `export`. |
|
|
@@ -298,7 +307,7 @@ Full flags and edge cases: see [reference.md](reference.md) `init` section.
|
|
|
298
307
|
| `export` | query-only+ | SQL, MongoDB, or **(v1.22)** Elasticsearch (DSL `--index` or whole-index scroll). Query → `--format json\|jsonl\|csv\|html` file or stdout. `html` emits a standalone interactive dashboard. Supports `--recovery`. |
|
|
299
308
|
| `blacklist` | n/a | `list` / `table` / `column` subcommands redact sensitive data from query results. |
|
|
300
309
|
| `check` | query-only+ | SQL only (best on MySQL/MariaDB). |
|
|
301
|
-
| `diff` | query-only+ | SQL only. Save/compare schema snapshots. |
|
|
310
|
+
| `diff` | query-only+ | SQL only. Save/compare schema snapshots. **(P1b)** `--against-orm <path>` compares a Prisma schema / DDL file / normalized JSON against the local schema cache (no DB connection): categorized drift (`missing_in_db` = error, `missing_in_orm` = warn, `mismatch` per tolerance table, `unmanaged`) with dry-run `migrate` proposals; exit 1 on error-level drift. `--orm-format prisma\|ddl\|json\|drizzle\|typeorm\|sequelize`, `--ignore <globs>`, `--format json\|table\|markdown`. Drizzle: point at `drizzle/meta/<NNNN>_snapshot.json` (run `drizzle-kit generate` first; `.ts` sources are rejected with a hint). TypeORM/Sequelize: feed tool-generated DDL (`schema:log` / a schema-only dump); source files are rejected with the exact generation command to run. |
|
|
302
311
|
| `snapshot` | query-only+ | **(v1.25)** SQL only. Capture a result fingerprint (`rowCount` + per-column null/distinct/min/max/sum + order-independent checksum). `--out` (default `.dbcli/snapshots/snap-<ts>.json`), `--rows`, `--stdout`, `--format`, `--no-limit`. Baseline for `assert --against`. |
|
|
303
312
|
| `assert` | query-only+ | **(v1.25)** SQL only. Verify an invariant; exit 1 on failure unless `--no-fail`. `--expect "rows>0\|value==X\|col:c not null\|unique\|between a and b\|>= n"`, `--vs <query> --compare rows\|value` (reconcile), `--against <snapshot> --tolerance <pct>`. |
|
|
304
313
|
| `verification` | n/a | Inspect and manage local verification artifacts. `list` / `show <id-or-path>` / `summary` are read-only; `prune` is dry-run by default and deletes only with `--execute --force`. Reads `<cwd>/.dbcli/verification/`; no DB connection, no audit writes. |
|
|
@@ -318,7 +327,7 @@ Full flags and edge cases: see [reference.md](reference.md) `init` section.
|
|
|
318
327
|
|
|
319
328
|
`--use <name>` on any subcommand (including `status` / `doctor`) targets a v2 connection
|
|
320
329
|
without changing the default. `--recovery` is honoured by `query`, `q`, `insert`, `update`,
|
|
321
|
-
`delete`, `export`, `schema`, and `
|
|
330
|
+
`delete`, `export`, `schema`, `inspect`, `lint`, and `diff --against-orm` (see **On failure** above).
|
|
322
331
|
|
|
323
332
|
**Write & query flag semantics** (SQL/Mongo `insert`/`update`):
|
|
324
333
|
|
package/assets/SKILL.zh-TW.md
CHANGED
|
@@ -40,13 +40,13 @@ description: Database CLI for AI agents with permission-based access control. Us
|
|
|
40
40
|
|
|
41
41
|
慢查詢診斷有三條標準路徑(依已掌握的資訊選擇):
|
|
42
42
|
|
|
43
|
-
- 已知慢 SQL → `skill tasks plan diagnose-slow-query --param query="<SQL>"` → `guide missing-index-for "<SQL>"`
|
|
43
|
+
- 已知慢 SQL → `skill tasks plan diagnose-slow-query --param query="<SQL>"` → `lint "<SQL>"` → `guide missing-index-for "<SQL>"`
|
|
44
44
|
- 已知熱點資料表 → `skill tasks plan analyze-table-perf --param table=<table>`
|
|
45
45
|
- 全環境掃描 → `report --section perf` → `guide slow-query`
|
|
46
46
|
|
|
47
47
|
`report --section perf` 已涵蓋 slow-query、index-usage 與 cache-hit 診斷 — 之後只需補上它未涵蓋的 `@diag/*`(`missing-indexes`、`locks`、`connections`、`table-sizes`)。一旦鎖定特定慢語句,`explain --analyze "<SQL>"` 可顯示執行計畫。
|
|
48
48
|
|
|
49
|
-
**失敗時:** 在 `query` / `q` / `insert` / `update` / `delete` / `export` / `schema` / `inspect` 加上 `--recovery`。指令會把 `RecoveryEnvelope` 輸出到 stdout 並儲存到 `.dbcli/last-recovery.json`;然後用 `dbcli recover` 檢視、`dbcli recover --apply` 在風險門控下執行儲存的計畫。Multi-turn `--next`、連線分支與 post-apply 驗證探針詳見 reference.md §Recovery Cookbook。
|
|
49
|
+
**失敗時:** 在 `query` / `q` / `insert` / `update` / `delete` / `export` / `schema` / `inspect` / `lint` / `diff --against-orm` 加上 `--recovery`。指令會把 `RecoveryEnvelope` 輸出到 stdout 並儲存到 `.dbcli/last-recovery.json`;然後用 `dbcli recover` 檢視、`dbcli recover --apply` 在風險門控下執行儲存的計畫。Multi-turn `--next`、連線分支與 post-apply 驗證探針詳見 reference.md §Recovery Cookbook。
|
|
50
50
|
|
|
51
51
|
回報驗證結果時使用詞彙:`verified`(證據符合)/ `not_verified`(驗證執行但結果矛盾)/ `indeterminate`(執行但證據不明確)/ `blocked`(因 config、權限、schema、placeholder 或安全閘門導致無法執行)。
|
|
52
52
|
|
|
@@ -64,7 +64,7 @@ dbcli skill tasks plan <task> --param key=value --format json # generate pla
|
|
|
64
64
|
|
|
65
65
|
計畫輸出是一組附帶說明與風險標籤的 dbcli 指令序列。請逐一執行 — 任務計畫**不會**繞過 blacklist、schema、dry-run 或確認等要求。
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
內建套件(SQL — postgres/mysql):`diagnose-slow-query`(針對特定 SQL)、`analyze-table-perf`(針對特定資料表;`dbcli inspect` 會針對近期 audit 活動中最熱門的資料表自動建議此套件)、`audit-permissions`、`safe-backfill`、`schema-drift-review`、`orm-drift-review`(ORM 定義與快取 DB schema 比對)、`connection-health`。審查與驗證套件:`pr-database-review`、`migration-review`、`safe-backfill-verify`、`slow-endpoint-investigation`。MongoDB 套件:`mongo-safe-backfill`(以 dry-run 預覽的回填)、`mongo-schema-drift-review`(抽樣 dot-path 漂移)。全部為唯讀 `plan-only` — 選擇符合使用者情境的套件,任何索引 / DDL 提案都應先經 `migration-review` 再寫入。Redis/Elasticsearch 目前尚無套件——請改以 `guide` / `report` 為主。
|
|
68
68
|
|
|
69
69
|
任務檔放在 `assets/tasks/`(內建)、`.dbcli-shared/tasks/`(共享)與 `.dbcli/tasks/`(本地覆寫)。
|
|
70
70
|
|
|
@@ -77,9 +77,9 @@ dbcli skill tasks plan <task> --param key=value --format json # generate pla
|
|
|
77
77
|
| DB-backed 功能 | `blacklist list` → `schema <object>` → `queries suggest <intent>` |
|
|
78
78
|
| DB report / dashboard request | `blacklist list` → `queries search <keywords>` / `queries suggest <intent>` → `queries show @<name>` → `q @<name> --ui` 或 `--format html` |
|
|
79
79
|
| 應用程式資料錯誤 | `audit tail --for-agent --n 10` → `blacklist list` → `schema <object>` → 最小查詢 |
|
|
80
|
-
| ORM 或 migration | `schema --format json` → `diff --
|
|
80
|
+
| ORM 或 migration | `schema --format json` → `diff --against-orm <orm-schema>` → 審查 error-level drift → 透過 `migrate` 取得提案(dry-run)→ `migration-review` task pack → 套用後執行 `diff --against <snapshot>`。 |
|
|
81
81
|
| PR 資料庫風險審查 | 審查變更的 persistence path,並針對每個重要主張提出具體 `schema`、`plan`、`dry-run`、`report` 或 `guide` 指令。 |
|
|
82
|
-
| 慢 endpoint 或查詢 | `report --section perf` → task pack `analyze-table-perf` → `guide missing-index-for "<query>"`;有 proxy log 時使用 `proxy analyze`。 |
|
|
82
|
+
| 慢 endpoint 或查詢 | `report --section perf` → task pack `analyze-table-perf` → `lint "<query>"` → `guide missing-index-for "<query>"`;有 proxy log 時使用 `proxy analyze`。 |
|
|
83
83
|
| 安全資料回填 | `blacklist list` → `schema <object>` → count/scope query → `update … --dry-run` → read-back 或 snippet `--verify`。 |
|
|
84
84
|
| 環境設定驗證 | `status --format json` → `doctor --format json` → `inspect --for-agent --no-connect`。 |
|
|
85
85
|
|
|
@@ -95,9 +95,13 @@ dbcli q @<name> --param k=v --format html > report.html
|
|
|
95
95
|
dbcli export "<SQL>" --format html --output report.html
|
|
96
96
|
dbcli audit tail --for-agent --n 10
|
|
97
97
|
dbcli diff --snapshot <name>
|
|
98
|
+
dbcli diff --against-orm prisma/schema.prisma --format json
|
|
99
|
+
dbcli diff --against-orm "migrations/*.sql" --format markdown
|
|
100
|
+
dbcli skill tasks plan orm-drift-review --param orm_path=prisma/schema.prisma --format json
|
|
98
101
|
dbcli report --section perf --format json
|
|
99
102
|
dbcli skill tasks plan analyze-table-perf --param table=<table> --format json
|
|
100
103
|
dbcli guide missing-index-for "<query>" --format json
|
|
104
|
+
dbcli lint "<SQL>" --format json
|
|
101
105
|
dbcli update <object> --where "<bounded predicate>" --set '<json>' --dry-run --format json
|
|
102
106
|
dbcli inspect --for-agent --no-connect --format json
|
|
103
107
|
```
|
|
@@ -232,6 +236,7 @@ dbcli init --conn-name prod --env-file .env.production --use-env-refs --skip-tes
|
|
|
232
236
|
| `schema` | query-only+ | SQL:單表或全掃描存入 `.dbcli/schemas/`。MongoDB:sampled。ES:flattened mapping。Redis:僅單一 key(type / TTL / size)。支援 `--recovery`。 |
|
|
233
237
|
| `query` | query-only+ | SQL、Mongo JSON(`--collection`)、Redis 指令、ES DSL / Lucene(`--collection`)。`--format table\|json\|csv\|html`、`--ui` 開啟瀏覽器互動式 dashboard。支援 `--recovery`。 |
|
|
234
238
|
| `explain` | query-only+ | **(v1.23)** 唯讀查詢計畫並附註解。僅 SQL。單一查詢、`@saved-query`、`@file.sql` 或 `--bulk @glob/*`。`--analyze`(EXPLAIN ANALYZE / MariaDB ANALYZE SELECT)、`--format markdown\|json\|table`。 |
|
|
239
|
+
| `lint` | n/a | 靜態 SQL 反模式顧問(不連線 DB)。共 9 條規則,包含透過分層 `.dbcli/schemas/` 快取進行的 schema-aware implicit-cast / NOT IN-nullable 檢查;全域 `--use <conn>` 會選擇命名連線的快取。Finding 可附 rewrite 草稿與受保護的 `explain` 驗證指令;只有已證明唯讀的 SQL 才會加上 `--analyze`,且只回報、絕不執行。`--format text\|json\|markdown`、`--min-severity`、`--no-schema`、`--bulk`。支援 `--recovery`。 |
|
|
235
240
|
| `plan` | n/a | 靜態 SQL 風險分析器(`--format text\|json`);不連線即可分類語句。 |
|
|
236
241
|
| `q` | query-only+ | 以 `@name` 執行已儲存 snippet,搭配 `--param k=v`。支援 `--verify` 以執行斷言。 |
|
|
237
242
|
| `queries` | n/a | 管理已儲存 snippet:`list` / `show` / `search` / `suggest` / `new` / `edit` / `check` / `delete` / `rename` / `copy` / `import` / `export`。 |
|
|
@@ -240,7 +245,7 @@ dbcli init --conn-name prod --env-file .env.production --use-env-refs --skip-tes
|
|
|
240
245
|
| `export` | query-only+ | SQL、MongoDB 或 **(v1.22)** Elasticsearch(DSL `--index` 或全 index scroll)。Query → `--format json\|jsonl\|csv\|html` 檔案或 stdout。`html` 輸出獨立可互動 dashboard。支援 `--recovery`。 |
|
|
241
246
|
| `blacklist` | n/a | `list` / `table` / `column` 子指令,從查詢結果中遮蔽敏感資料。 |
|
|
242
247
|
| `check` | query-only+ | 僅 SQL(在 MySQL / MariaDB 最佳)。 |
|
|
243
|
-
| `diff` | query-only+ | 僅 SQL。儲存 / 比較 schema snapshot
|
|
248
|
+
| `diff` | query-only+ | 僅 SQL。儲存 / 比較 schema snapshot。**(P1b)** `--against-orm <path>` 會將 Prisma schema / DDL 檔 / normalized JSON 與本地 schema cache 比對(不連線 DB):分類為 `missing_in_db`(error)、`missing_in_orm`(warn)、依 tolerance 表判定的 `mismatch`、以及 `unmanaged`,並提供 dry-run `migrate` 提案;出現 error-level drift 時 exit 1。`--orm-format prisma\|ddl\|json\|drizzle\|typeorm\|sequelize`、`--ignore <globs>`、`--format json\|table\|markdown`。Drizzle:請指向 `drizzle/meta/<NNNN>_snapshot.json`(先執行 `drizzle-kit generate`;`.ts` source 會被拒絕並顯示提示)。TypeORM/Sequelize:傳入工具產生的 DDL(`schema:log` / schema-only dump);source file 會被拒絕,並顯示要執行的精確產生指令。 |
|
|
244
249
|
| `snapshot` | query-only+ | **(v1.25)** 僅 SQL。擷取結果指紋(`rowCount` + 每欄 null/distinct/min/max/sum + 順序無關 checksum)。`--out`(預設 `.dbcli/snapshots/snap-<ts>.json`)、`--rows`、`--stdout`、`--format`、`--no-limit`。作為 `assert --against` 的基準。 |
|
|
245
250
|
| `assert` | query-only+ | **(v1.25)** 僅 SQL。驗證不變量;失敗時 exit 1,除非 `--no-fail`。`--expect "rows>0\|value==X\|col:c not null\|unique\|between a and b\|>= n"`、`--vs <query> --compare rows\|value`(對帳)、`--against <snapshot> --tolerance <pct>`。 |
|
|
246
251
|
| `verification` | n/a | 檢視與管理本機驗證 artifact。`list` / `show <id-or-path>` / `summary` 為唯讀;`prune` 預設 dry-run,僅在 `--execute --force` 時刪除。讀取 `<cwd>/.dbcli/verification/`;不需 DB 連線,不寫入 audit log。 |
|
|
@@ -258,7 +263,7 @@ dbcli init --conn-name prod --env-file .env.production --use-env-refs --skip-tes
|
|
|
258
263
|
| `skill` | n/a | 產出 / 安裝 AI skill 文件(`--install <claude\|gemini\|antigravity\|copilot\|cursor\|codex\|windsurf>`);`skill tasks list/show/plan` 提供 Agent Task Packs;`skill context` 提供 LLM 提示詞脈絡載荷(用於注入其他 LLM,正常操作不需要)。 |
|
|
259
264
|
| `migrate` | admin | 僅 SQL。**DDL;預設 dry-run** — 需 `--execute`。 |
|
|
260
265
|
|
|
261
|
-
任何子指令上的 `--use <name>` 可在不改變預設值的情況下,把目標切到 v2 連線。`--recovery` 被 `query`、`q`、`insert`、`update`、`delete`、`export`、`schema` 與 `
|
|
266
|
+
任何子指令上的 `--use <name>` 可在不改變預設值的情況下,把目標切到 v2 連線。`--recovery` 被 `query`、`q`、`insert`、`update`、`delete`、`export`、`schema`、`inspect`、`lint` 與 `diff --against-orm` 支援(見上方**失敗時**)。
|
|
262
267
|
|
|
263
268
|
**寫入與查詢旗標語意**(SQL / Mongo `insert`/`update`):
|
|
264
269
|
|