@carllee1983/dbcli 1.5.2 → 1.7.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.
@@ -0,0 +1,510 @@
1
+ # dbcli — full command reference
2
+
3
+ Companion to [SKILL.md](SKILL.md). Exhaustive flags, copy-paste examples, `shell`, `completion`, `upgrade`, `migrate` DDL, and extended MongoDB examples.
4
+
5
+ For cross-engine support status, see `docs/feature-matrix.md` in the repository.
6
+
7
+ ## Commands
8
+
9
+ ### init
10
+
11
+ Initialize `.dbcli` configuration file. Typically run manually by the developer — avoid running on behalf of the user unless explicitly requested.
12
+
13
+ ```bash
14
+ dbcli init # Single connection (v1 format)
15
+ dbcli init --system mysql --host localhost --port 3306 --user root --name mydb
16
+ dbcli init --use-env-refs # Store env var references
17
+ dbcli init --no-interactive --force # Non-interactive mode
18
+
19
+ # MongoDB
20
+ dbcli init --system mongodb --uri "mongodb://user:pass@host:27017/mydb?authSource=admin"
21
+ dbcli init --system mongodb --host localhost --port 27017 --user admin --password secret --name mydb
22
+ dbcli init --system mongodb --host localhost --port 27017 --name mydb # No auth
23
+
24
+ # Multi-connection (v2 format)
25
+ dbcli init --conn-name staging --env-file .env.staging # Named connection with custom env file
26
+ dbcli init --conn-name prod --env-file .env.production --use-env-refs --skip-test
27
+ dbcli init --remove staging # Remove a named connection
28
+ dbcli init --rename staging:production # Rename a connection
29
+ ```
30
+
31
+ **Key options:** `--system`, `--permission`, `--use-env-refs`, `--skip-test`, `--no-interactive`, `--force`, `--conn-name <name>`, `--env-file <path>`, `--remove <name>`, `--rename <old:new>`
32
+
33
+ **MongoDB-specific options:** `--uri <uri>` (full connection URI), `--auth-source <db>` (auth database, default: `admin` when user/password set)
34
+
35
+ **Multi-connection:** Using `--conn-name` or `--env-file` creates a v2 config with named connections. Each connection can have its own env file and permission level. Existing v1 configs are automatically imported as the `default` connection when upgrading.
36
+
37
+ > **AI agent note on `--use-env-refs`:** If an existing `.dbcli` config contains `{"$env": "DB_HOST"}` style references, the connection values are read from environment variables at runtime. Do NOT re-run `init` to replace these references with actual values — the env-ref format is intentional for CI/CD and multi-environment setups.
38
+
39
+ ### use
40
+
41
+ Switch or display the default database connection (v2 multi-connection config).
42
+
43
+ ```bash
44
+ dbcli use # Show current default connection
45
+ dbcli use staging # Switch default to 'staging'
46
+ dbcli use --list # List all connections (* marks default)
47
+ ```
48
+
49
+ Any command can also use `--use <name>` to temporarily select a connection without changing the default:
50
+
51
+ ```bash
52
+ dbcli query --use staging "SELECT * FROM users LIMIT 10"
53
+ dbcli list --use prod
54
+ ```
55
+
56
+ **Requires v2 config** (created with `dbcli init --conn-name`).
57
+
58
+ ### list
59
+
60
+ List all tables (SQL) or collections (MongoDB).
61
+
62
+ ```bash
63
+ dbcli list
64
+ dbcli list --format json
65
+ ```
66
+
67
+ **Permission:** query-only+
68
+
69
+ > **MongoDB:** Lists collections with estimated document count instead of tables.
70
+
71
+ ### schema
72
+
73
+ Display table schema or scan entire database.
74
+
75
+ ```bash
76
+ dbcli schema # Scan all tables, save to .dbcli/schemas/
77
+ dbcli schema users # Show single table schema
78
+ dbcli schema users --format json
79
+ dbcli schema --refresh # Detect and apply schema changes
80
+ dbcli schema --reset # Clear all schema data and re-fetch
81
+ dbcli schema --reset --force # Skip confirmation
82
+
83
+ # Per-connection schema isolation (v2 multi-connection config)
84
+ dbcli schema --use staging # Scan staging DB; saves to .dbcli/schemas/staging/
85
+ dbcli schema --use prod # Scan prod DB; saves to .dbcli/schemas/prod/
86
+ ```
87
+
88
+ **Options:** `--format <table|json>`, `--refresh`, `--reset`, `--force`, `--use <connection>`
89
+ **Permission:** query-only+
90
+
91
+ **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.
92
+
93
+ ### query
94
+
95
+ Execute SQL query (MySQL/PostgreSQL/MariaDB) or JSON filter/pipeline (MongoDB).
96
+
97
+ ```bash
98
+ # SQL databases
99
+ dbcli query "SELECT * FROM users LIMIT 10"
100
+ dbcli query "SELECT id, email FROM users" --format json
101
+ dbcli query "SELECT * FROM logs" --no-limit
102
+
103
+ # MongoDB: JSON filter (find)
104
+ dbcli query '{"status": "active"}' --collection users
105
+ dbcli query '{"age": {"$gt": 18}}' --collection users --format json
106
+
107
+ # MongoDB: aggregation pipeline
108
+ dbcli query '[{"$match": {"status": "active"}}, {"$group": {"_id": "$role", "count": {"$sum": 1}}}]' --collection users
109
+ ```
110
+
111
+ **Options:** `--format <table|json|csv>`, `--limit <number>`, `--no-limit`, `--collection <name>` (MongoDB only)
112
+ **Permission:** query-only+
113
+
114
+ > **MongoDB notes:**
115
+ > - SQL syntax is rejected — use JSON object (filter) or JSON array (pipeline)
116
+ > - `--collection <name>` is required
117
+ > - Auto-limit does not apply; use `$limit` in your pipeline if needed
118
+
119
+ ### q
120
+
121
+ Run a saved query snippet by `@name`. Snippets are parameterised SELECT/WITH statements resolved from three layers, with **local > shared > builtin** precedence (a local file always shadows shared and builtin variants of the same key):
122
+
123
+ - `builtin` — bundled with dbcli (e.g. `@diag/*`); read-only at runtime.
124
+ - `.dbcli-shared/queries/` — committed, team-shared.
125
+ - `.dbcli/queries/` — gitignored, personal override.
126
+
127
+ Engine variants (`name.postgres.sql` / `name.mysql.sql`) at the same layer are merged; the variant matching the active connection's engine is selected at execution time.
128
+
129
+ ```bash
130
+ dbcli q @dau # run with declared defaults
131
+ dbcli q @dau --param days=30 --format json # override a param
132
+ dbcli q @analytics/revenue --param-file params.json
133
+ dbcli q @dau --dry-run # show final SQL + bind values
134
+ dbcli q @dau --no-limit # disable size guard wrap
135
+ ```
136
+
137
+ **Options:**
138
+ - `--format <table|json|csv>` — output format (default: `table`)
139
+ - `--param <key=value>` — pass a parameter (repeatable)
140
+ - `--param-file <path>` — JSON object whose keys are param names
141
+ - `--no-limit` — skip the `SELECT * FROM (…) AS _dbcli_guard LIMIT 1000` wrap
142
+ - `--dry-run` — print the bound SQL + values without executing
143
+ - `--use <name>` — pick a v2 named connection
144
+
145
+ **Permission:** query-only+
146
+
147
+ #### Snippet file format
148
+
149
+ Each `.sql` file is plain SQL with optional YAML frontmatter inside a leading `-- ---` block. Lines outside frontmatter form the SQL body.
150
+
151
+ ```sql
152
+ -- ---
153
+ -- name: DAU
154
+ -- description: Daily Active Users
155
+ -- engine: postgres # or [postgres, mysql]
156
+ -- params:
157
+ -- days:
158
+ -- type: int # int | string | float | bool | date | datetime
159
+ -- default: 7
160
+ -- required: false
161
+ -- description: lookback window in days
162
+ -- enum: [7, 30, 90]
163
+ -- tags: [analytics]
164
+ -- ---
165
+ SELECT COUNT(DISTINCT user_id) AS dau
166
+ FROM events
167
+ WHERE created_at > NOW() - (:days || ' days')::interval;
168
+ ```
169
+
170
+ Param placeholders use `:name`. They are rewritten to `$1, $2, …` (Postgres) or `?, ?, …` (MySQL) at execution time and passed as bind values — string interpolation is never used.
171
+
172
+ #### Param type coercion
173
+
174
+ | Declared `type` | Accepts |
175
+ |-----------------|---------|
176
+ | `int` | integer literal |
177
+ | `float` | decimal literal |
178
+ | `bool` | `true` / `false` / `1` / `0` / `yes` / `no` |
179
+ | `string` | any value |
180
+ | `date` | `YYYY-MM-DD` |
181
+ | `datetime` | ISO 8601 |
182
+
183
+ `enum` (optional) restricts the accepted values; mismatch is a hard error. CLI `--param` overrides `--param-file`, which overrides the snippet's `default`.
184
+
185
+ #### Safety invariants
186
+
187
+ - Only `SELECT` / `WITH` (CTE) bodies are accepted; `INSERT/UPDATE/DELETE/DDL` are rejected by the parser.
188
+ - Multi-statement bodies (`SELECT 1; DROP TABLE x`) are rejected.
189
+ - Template syntax inside SQL (`${…}`, `{{…}}`) is rejected — use `:name` parameters.
190
+ - Files exceeding 64 KiB are rejected.
191
+ - `--no-limit` is honoured only at the outermost level; nested subqueries are still wrapped by the size guard.
192
+
193
+ ### queries
194
+
195
+ Manage saved snippets — discover, inspect, scaffold, and edit local copies. Mutating
196
+ subcommands (`delete`, `rename`, `copy`, `import`) only operate on the local layer
197
+ (`.dbcli/queries/`); builtin and shared snippets are never modified in place.
198
+
199
+ ```bash
200
+ # Discovery / inspection
201
+ dbcli queries list # all snippets (builtin + shared + local)
202
+ dbcli queries list --tag analytics --engine postgres --format json
203
+ dbcli queries list --source local # only personal overrides
204
+ dbcli queries show @dau # frontmatter + SQL
205
+ dbcli queries show @dau --format json # MCP-shaped contract
206
+
207
+ # Authoring
208
+ dbcli queries new @new/sample # scaffold under .dbcli-shared/queries/
209
+ dbcli queries new @scratch --local # personal copy under .dbcli/queries/
210
+ dbcli queries edit @dau # opens local first, falls back to shared
211
+ dbcli queries edit @dau --shared # always edit the shared file
212
+ dbcli queries check # parse all snippets; exit 1 on errors
213
+ dbcli queries check --strict # promote warnings (e.g. missing engine) to errors
214
+
215
+ # Local-layer file management
216
+ dbcli queries delete @scratch # remove local file(s); prompts unless --force
217
+ dbcli queries delete @scratch --force
218
+ dbcli queries rename @scratch @analytics/dau # rename within local layer; preserves engine suffix
219
+ dbcli queries copy @diag/connections @my/connections # fork builtin/shared into local for editing
220
+ dbcli queries import ./hotfix.sql # import an external .sql into .dbcli/queries/
221
+ dbcli queries import ./hotfix.sql --as @diag/custom # override the snippet key
222
+ dbcli queries export @dau --output dau.sql # write snippet body to a file (stdout if omitted)
223
+ dbcli queries export @diag/connections --engine postgres # pick a variant when multiple engines exist
224
+ ```
225
+
226
+ **`list` options:** `--format <table|json|csv>`, `--tag <tag>`, `--engine <postgres|mysql>`, `--source <local|shared>`
227
+ **`show` options:** `--format <table|json|csv>`
228
+ **`new` options:** `--local`, `--edit`
229
+ **`edit` options:** `--shared`
230
+ **`check` options:** `--strict`, `--format <table|json|csv>`
231
+ **`delete` options:** `--force` (skip the confirmation prompt). Refuses to run if `@name` has no local copy.
232
+ **`rename` options:** `--force`. Both names must start with `@`. Engine suffix (`.postgres.sql` / `.mysql.sql`) is preserved; frontmatter `name:` is rewritten to the new key.
233
+ **`copy` options:** *(none)*. Copies every variant (all engines) of the source into the local layer; fails if the destination already has a local copy.
234
+ **`import` options:** `--force` (overwrite existing local file), `--as <name>` (override snippet key; defaults to filename without `.postgres` / `.mysql` suffix). Source must be `.sql` and parse cleanly (frontmatter validated, non-SELECT bodies rejected).
235
+ **`export` options:** `--output <path>` (write to file; otherwise stdout), `--engine <postgres|mysql>` (required when the snippet has multiple engine variants).
236
+
237
+ `--format json` on `list` and `show` emits a stable, machine-readable shape — designed to back a future MCP server without further refactor.
238
+
239
+ ### insert
240
+
241
+ Insert data into a table.
242
+
243
+ ```bash
244
+ dbcli insert users --data '{"name":"Alice","email":"alice@example.com"}'
245
+ dbcli insert users --data '{"name":"Alice"}' --dry-run
246
+ dbcli insert users --data '{"name":"Alice"}' --force
247
+ ```
248
+
249
+ **Options:** `--data <json>`, `--dry-run`, `--force`
250
+ **Permission:** read-write+
251
+
252
+ ### update
253
+
254
+ Update existing data.
255
+
256
+ ```bash
257
+ dbcli update users --where "id=1" --set '{"name":"Bob"}'
258
+ dbcli update users --where "id=1" --set '{"name":"Bob"}' --dry-run
259
+ ```
260
+
261
+ **Options:** `--where <condition>` (required), `--set <json>` (required), `--dry-run`, `--force`
262
+ **Permission:** read-write+
263
+
264
+ ### delete
265
+
266
+ Delete data from a table.
267
+
268
+ ```bash
269
+ dbcli delete users --where "id=1"
270
+ dbcli delete users --where "id=1" --dry-run
271
+ dbcli delete users --where "id=1" --force
272
+ ```
273
+
274
+ **Options:** `--where <condition>` (required), `--dry-run`, `--force`
275
+ **Permission:** data-admin+
276
+
277
+ ### export
278
+
279
+ Export query results to file or stdout.
280
+
281
+ ```bash
282
+ dbcli export "SELECT * FROM users" --format csv --output users.csv
283
+ dbcli export "SELECT * FROM users" --format csv --output users.csv --force # Skip overwrite confirmation
284
+ dbcli export "SELECT * FROM users" --format json | jq '.[]'
285
+ ```
286
+
287
+ **Options:** `--format <json|csv>` (required), `--output <path>`, `--force`
288
+ **Permission:** query-only+
289
+
290
+ ### blacklist
291
+
292
+ Manage sensitive data blacklist to prevent AI access to restricted tables/columns.
293
+
294
+ ```bash
295
+ dbcli blacklist list # Show current blacklist
296
+ dbcli blacklist table add payments # Block entire table
297
+ dbcli blacklist table remove payments # Unblock table
298
+ dbcli blacklist column add users.password # Block specific column
299
+ dbcli blacklist column remove users.password
300
+ ```
301
+
302
+ **Subcommands:** `list`, `table add <name>`, `table remove <name>`, `column add <table.column>`, `column remove <table.column>`
303
+
304
+ ### check
305
+
306
+ Run data health checks on tables.
307
+
308
+ ```bash
309
+ dbcli check users # Check single table
310
+ dbcli check users --format json # JSON output (default)
311
+ dbcli check --all # Check all tables (huge tables auto-skipped)
312
+ dbcli check --all --include-large # Include huge tables
313
+ dbcli check orders --checks nulls,orphans # Specific checks only
314
+ dbcli check orders --sample 10000 # Sample size for large tables
315
+ ```
316
+
317
+ **Checks:** `nulls`, `duplicates`, `orphans`, `emptyStrings`, `rowCount`, `size`
318
+ **Options:** `--all`, `--include-large`, `--checks <types>`, `--sample <number>`, `--format <json|table>`
319
+ **Permission:** query-only+
320
+
321
+ ### diff
322
+
323
+ Compare schema snapshots to detect changes.
324
+
325
+ ```bash
326
+ dbcli diff --snapshot before.json # Save current schema snapshot
327
+ dbcli diff --against before.json # Compare current vs snapshot
328
+ dbcli diff --against before.json --format json
329
+ ```
330
+
331
+ **Options:** `--snapshot <path>`, `--against <path>`, `--format <json|table>`
332
+ **Permission:** query-only+
333
+
334
+ ### status
335
+
336
+ Show current configuration status (safe for AI agents, no credentials exposed).
337
+
338
+ ```bash
339
+ dbcli status # JSON output (default)
340
+ dbcli status --format text # Human-readable text output
341
+ ```
342
+
343
+ **Output:** `permission`, `system`, `blacklist` summary, `version`
344
+ **Permission:** query-only+
345
+
346
+ ### doctor
347
+
348
+ Run diagnostic checks on environment, configuration, connection, and data.
349
+
350
+ ```bash
351
+ dbcli doctor # Colored text output
352
+ dbcli doctor --format json # JSON output for AI agents
353
+ ```
354
+
355
+ **Checks:**
356
+ - Environment: Bun version, dbcli version (compares with npm registry)
357
+ - Configuration: config file exists/valid, permission level, blacklist completeness (detects unprotected sensitive columns)
358
+ - Connection & Data: database connectivity, schema cache freshness (warns if > 7 days), large table warnings (> 1M rows)
359
+
360
+ > **MongoDB SRV diagnostics:** When the active connection uses `mongodb+srv://`, `doctor` reports whether the current runtime can resolve SRV records directly or only through the DNS-over-HTTPS fallback used by dbcli. This helps spot execution-environment DNS restrictions even when Compass can connect.
361
+
362
+ **Exit code:** 0 if all pass or warnings only, 1 if any error
363
+ **Options:** `--format <text|json>`
364
+
365
+ ### completion
366
+
367
+ Generate shell completion scripts for tab auto-complete.
368
+
369
+ ```bash
370
+ dbcli completion bash # Output bash completion script
371
+ dbcli completion zsh # Output zsh completion script
372
+ dbcli completion fish # Output fish completion script
373
+ dbcli completion --install # Auto-detect shell and install
374
+ dbcli completion --install zsh # Install for specific shell
375
+ ```
376
+
377
+ **Supported shells:** bash, zsh, fish
378
+
379
+ ### upgrade
380
+
381
+ Check for updates and self-upgrade dbcli to the latest version from npm.
382
+
383
+ ```bash
384
+ dbcli upgrade # Check and upgrade if newer version available
385
+ dbcli upgrade --check # Only check, do not upgrade
386
+ ```
387
+
388
+ **Options:** `--check`
389
+
390
+ **Background check:** Every command silently checks the npm registry for a newer version (at most once per 24 hours, cached in `.dbcli/version-check.json`). If a newer version is found, a one-line hint is printed to stderr after the command completes. Pass `-q` / `--quiet` to suppress the hint.
391
+
392
+ ### `dbcli shell`
393
+
394
+ Start an interactive database shell.
395
+
396
+ ```bash
397
+ dbcli shell # Interactive mode with SQL + dbcli commands
398
+ dbcli shell --sql # SQL-only mode
399
+ ```
400
+
401
+ Inside the shell:
402
+ - Type SQL statements ending with `;` to execute
403
+ - Type dbcli commands without the `dbcli` prefix (e.g., `schema users`)
404
+ - Use Tab for auto-completion (SQL keywords, table names, column names)
405
+ - Type `.help` for meta commands (.quit, .clear, .format, .history, .timing)
406
+ - Multi-line SQL: keeps accumulating until `;` is found
407
+ - History persists across sessions (~/.dbcli_history)
408
+
409
+ ### migrate
410
+
411
+ Schema DDL operations. **All commands default to dry-run** — use `--execute` to actually run the SQL. Destructive operations (DROP) also require `--force`.
412
+
413
+ ```bash
414
+ # Create table
415
+ dbcli migrate create posts \
416
+ --column "id:serial:pk" \
417
+ --column "title:varchar(200):not-null" \
418
+ --column "body:text" \
419
+ --column "created_at:timestamp:default=now()"
420
+
421
+ # Drop table (dry-run by default)
422
+ dbcli migrate drop posts
423
+ dbcli migrate drop posts --execute --force # Actually drop
424
+
425
+ # Add/drop/alter column
426
+ dbcli migrate add-column users bio text --nullable
427
+ dbcli migrate drop-column users temp_field --execute --force
428
+ dbcli migrate alter-column users name --type "varchar(200)"
429
+ dbcli migrate alter-column users email --rename user_email
430
+ dbcli migrate alter-column users status --set-default "'active'"
431
+ dbcli migrate alter-column users bio --drop-default
432
+ dbcli migrate alter-column users bio --set-nullable
433
+ dbcli migrate alter-column users email --drop-nullable
434
+
435
+ # Index management
436
+ dbcli migrate add-index users --columns email --unique
437
+ dbcli migrate add-index users --columns "last_name,first_name" --name idx_fullname
438
+ dbcli migrate drop-index idx_fullname --execute --force
439
+
440
+ # Constraint management
441
+ dbcli migrate add-constraint orders --fk user_id --references users.id --on-delete cascade
442
+ dbcli migrate add-constraint users --unique email
443
+ dbcli migrate add-constraint users --check "age >= 0"
444
+ dbcli migrate drop-constraint orders fk_orders_user_id --execute --force
445
+
446
+ # Enum (PostgreSQL only — MySQL uses inline ENUM in column type)
447
+ dbcli migrate add-enum status active inactive suspended
448
+ dbcli migrate alter-enum status --add-value archived
449
+ dbcli migrate drop-enum status --execute --force
450
+ ```
451
+
452
+ **Column spec format:** `name:type[:modifier[:modifier...]]`
453
+ - Modifiers: `pk`, `not-null`, `unique`, `auto-increment`, `default=<value>`, `references=<table>.<column>`
454
+ - Serial types: `serial`, `bigserial`, `smallserial` (auto-expand per DB dialect)
455
+
456
+ **Options (all subcommands):** `--execute`, `--force`, `--config <path>`
457
+ **Permission:** admin
458
+
459
+ **AI agent note:** Always use dry-run first (no `--execute`) to preview generated SQL. Only add `--execute` after confirming the SQL is correct. For DROP operations, both `--execute` and `--force` are required.
460
+
461
+ ## MongoDB Support
462
+
463
+ MongoDB connections use a JSON-based query model instead of SQL. Treat MongoDB support as a narrower document-database path, not as a full SQL feature equivalent.
464
+
465
+ Atlas-style `mongodb+srv://` URIs are supported. `list` and `query` run against the database configured for the connection, and `query` always requires `--collection <name>`.
466
+
467
+ **Supported commands:** `init`, `use`, `list`, `schema`, `query`, `insert`, `update`, `delete`, `status`, `shell`, `doctor`, `upgrade`, `completion`
468
+
469
+ **Limited support:**
470
+
471
+ - `schema` samples collection documents to infer field names/types. It does not provide relational constraints, primary keys, foreign keys, or reliable index metadata.
472
+ - `query` accepts only JSON object filters or aggregation pipeline arrays and always requires `--collection <name>`.
473
+ - `insert` inserts one JSON document into the named collection.
474
+ - `update` accepts a JSON filter in `--where` or simple `key=value` conditions. If `--set` does not use MongoDB update operators such as `$set`, dbcli wraps it in `$set`.
475
+ - `delete` deletes all documents matching the JSON/simple filter.
476
+ - MongoDB write paths do not currently provide the same SQL dry-run, relational schema validation, or column-level blacklist filtering guarantees as SQL writes.
477
+ - `shell` blocks raw SQL for MongoDB; use `query <json> --collection <name>` inside the shell.
478
+
479
+ **Not supported (exit with error):** `q` saved-query execution, `export`, `diff`, `migrate`
480
+
481
+ **Not a supported MongoDB target:** `check` is designed for relational health checks and emits SQL-style checks.
482
+
483
+ ### MongoDB-specific workflow
484
+
485
+ ```bash
486
+ # 1. Initialize (URI or individual params)
487
+ dbcli init --system mongodb --uri "mongodb+srv://user:pass@cluster.example.mongodb.net/mydb"
488
+
489
+ # 2. List collections
490
+ dbcli list --format json
491
+
492
+ # 3. Query with JSON filter (find) or pipeline (aggregate)
493
+ dbcli query '{}' --collection orders --format json # All documents
494
+ dbcli query '{"status": "paid"}' --collection orders # Filter
495
+ dbcli query '[{"$match": {"status":"paid"}}, {"$count":"total"}]' --collection orders # Pipeline
496
+
497
+ # 4. Document writes (permission-gated; no SQL dry-run semantics)
498
+ dbcli insert orders --data '{"status":"paid","total":42}'
499
+ dbcli update orders --where '{"status":"pending"}' --set '{"status":"paid"}'
500
+ dbcli delete orders --where '{"status":"cancelled"}' --force
501
+ ```
502
+
503
+ ### Query syntax
504
+
505
+ | Intent | Syntax |
506
+ |--------|--------|
507
+ | All documents | `'{}'` |
508
+ | Field filter | `'{"field": "value"}'` |
509
+ | Comparison | `'{"age": {"$gt": 18}}'` |
510
+ | Aggregation | `'[{"$match": {...}}, {"$group": {...}}]'` |
File without changes
@@ -0,0 +1,18 @@
1
+ # Built-in snippets
2
+
3
+ Files under this directory are bundled with dbcli and resolved at runtime as
4
+ the `builtin` tier. Every file is a valid `.sql` snippet.
5
+
6
+ ## Naming
7
+
8
+ - Single-engine variant: `<topic>.<engine>.sql` — loader derives key
9
+ `@<dir>/<topic>` and engine from the suffix.
10
+ - Cross-engine variant: `<topic>.sql` with explicit
11
+ `engine: [postgres, mysql]` in frontmatter.
12
+
13
+ ## Override
14
+
15
+ Users can shadow any built-in snippet by placing a same-key file in
16
+ `.dbcli-shared/queries/` (team) or `.dbcli/queries/` (personal). Override is
17
+ per-engine: a local `connections.postgres.sql` only shadows the postgres
18
+ variant; the mysql variant is still served from builtin.
@@ -0,0 +1,19 @@
1
+ -- ---
2
+ -- name: InnoDB buffer pool hit ratio (mysql)
3
+ -- description: Reads from disk vs. read requests from the buffer pool.
4
+ -- engine: mysql
5
+ -- ---
6
+ SELECT
7
+ (SELECT VARIABLE_VALUE FROM performance_schema.global_status
8
+ WHERE VARIABLE_NAME = 'Innodb_buffer_pool_reads') AS pool_reads,
9
+ (SELECT VARIABLE_VALUE FROM performance_schema.global_status
10
+ WHERE VARIABLE_NAME = 'Innodb_buffer_pool_read_requests') AS pool_read_requests,
11
+ ROUND(
12
+ 1 -
13
+ (SELECT VARIABLE_VALUE FROM performance_schema.global_status
14
+ WHERE VARIABLE_NAME = 'Innodb_buffer_pool_reads')
15
+ /
16
+ NULLIF(
17
+ (SELECT VARIABLE_VALUE FROM performance_schema.global_status
18
+ WHERE VARIABLE_NAME = 'Innodb_buffer_pool_read_requests'), 0)
19
+ , 4) AS hit_ratio;
@@ -0,0 +1,18 @@
1
+ -- ---
2
+ -- name: Cache hit ratio (postgres)
3
+ -- description: Heap and index buffer cache hit ratios across user tables.
4
+ -- engine: postgres
5
+ -- ---
6
+ SELECT SUM(heap_blks_read) AS heap_read,
7
+ SUM(heap_blks_hit) AS heap_hit,
8
+ ROUND(
9
+ SUM(heap_blks_hit)::numeric
10
+ / NULLIF(SUM(heap_blks_hit) + SUM(heap_blks_read), 0)
11
+ , 4) AS heap_hit_ratio,
12
+ SUM(idx_blks_read) AS idx_read,
13
+ SUM(idx_blks_hit) AS idx_hit,
14
+ ROUND(
15
+ SUM(idx_blks_hit)::numeric
16
+ / NULLIF(SUM(idx_blks_hit) + SUM(idx_blks_read), 0)
17
+ , 4) AS idx_hit_ratio
18
+ FROM pg_statio_user_tables;
@@ -0,0 +1,16 @@
1
+ -- ---
2
+ -- name: Active connections (mysql)
3
+ -- description: Non-sleep processes ordered by elapsed time.
4
+ -- engine: mysql
5
+ -- ---
6
+ SELECT id,
7
+ user,
8
+ host,
9
+ db,
10
+ command,
11
+ time AS duration_seconds,
12
+ state,
13
+ info AS query
14
+ FROM information_schema.processlist
15
+ WHERE command <> 'Sleep'
16
+ ORDER BY time DESC;
@@ -0,0 +1,16 @@
1
+ -- ---
2
+ -- name: Active connections (postgres)
3
+ -- description: Active sessions excluding idle, ordered by query start.
4
+ -- engine: postgres
5
+ -- ---
6
+ SELECT pid,
7
+ usename AS user,
8
+ application_name AS app,
9
+ client_addr AS client,
10
+ state,
11
+ NOW() - query_start AS duration,
12
+ query
13
+ FROM pg_stat_activity
14
+ WHERE state IS NOT NULL
15
+ AND state <> 'idle'
16
+ ORDER BY query_start;
@@ -0,0 +1,10 @@
1
+ -- ---
2
+ -- name: Database size (mysql)
3
+ -- description: Total data + index size per schema in MB.
4
+ -- engine: mysql
5
+ -- ---
6
+ SELECT table_schema AS `database`,
7
+ ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS size_mb
8
+ FROM information_schema.tables
9
+ GROUP BY table_schema
10
+ ORDER BY size_mb DESC;
@@ -0,0 +1,9 @@
1
+ -- ---
2
+ -- name: Database size (postgres)
3
+ -- description: Each database with pretty-printed total size.
4
+ -- engine: postgres
5
+ -- ---
6
+ SELECT datname AS database,
7
+ pg_size_pretty(pg_database_size(datname)) AS size
8
+ FROM pg_database
9
+ ORDER BY pg_database_size(datname) DESC;
@@ -0,0 +1,15 @@
1
+ -- ---
2
+ -- name: Index usage (mysql)
3
+ -- description: Index I/O wait counts ordered by total uses.
4
+ -- engine: mysql
5
+ -- ---
6
+ SELECT object_schema AS `schema`,
7
+ object_name AS `table`,
8
+ index_name,
9
+ count_star AS uses,
10
+ count_read AS reads,
11
+ count_write AS writes
12
+ FROM performance_schema.table_io_waits_summary_by_index_usage
13
+ WHERE object_schema NOT IN ('mysql','performance_schema','sys')
14
+ AND index_name IS NOT NULL
15
+ ORDER BY count_star ASC;
@@ -0,0 +1,14 @@
1
+ -- ---
2
+ -- name: Index usage (postgres)
3
+ -- description: Indexes ordered by scan count (low scans = candidates to drop).
4
+ -- engine: postgres
5
+ -- ---
6
+ SELECT schemaname AS schema,
7
+ relname AS table,
8
+ indexrelname AS index,
9
+ idx_scan AS scans,
10
+ idx_tup_read AS tuples_read,
11
+ idx_tup_fetch AS tuples_fetched,
12
+ pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
13
+ FROM pg_stat_user_indexes
14
+ ORDER BY idx_scan ASC;
@@ -0,0 +1,14 @@
1
+ -- ---
2
+ -- name: Lock waits (mysql)
3
+ -- description: InnoDB lock waits with waiting and blocking transactions.
4
+ -- engine: mysql
5
+ -- ---
6
+ SELECT waiting.trx_mysql_thread_id AS waiting_thread,
7
+ waiting.trx_query AS waiting_query,
8
+ blocking.trx_mysql_thread_id AS blocking_thread,
9
+ blocking.trx_query AS blocking_query
10
+ FROM performance_schema.data_lock_waits AS w
11
+ JOIN information_schema.innodb_trx AS waiting
12
+ ON w.requesting_engine_transaction_id = waiting.trx_id
13
+ JOIN information_schema.innodb_trx AS blocking
14
+ ON w.blocking_engine_transaction_id = blocking.trx_id;