Repository navigation
Docs: the Inspecting SQL guide page #767
Description
Parent
What to build
A reader finds one guide page, "Inspecting SQL", under Guide after Raw SQL, and leaves it able to see every statement Ferro sends and to render a query without running it. The page opens with the one-sentence what-it-is and the .sql() example on its first screen, then: turning the statement log on with two lines of logging, a captured record shown as a plain handler prints it and as the structured attributes a JSON handler sees, .sql() on all, count and update, what a secret column looks like in both (***), the catalog probe and transaction-control records a reader will notice on Postgres, and how to assert on records in a pytest test with caplog. The running example is an Account model with a SecretStr token, declared in both field-declaration styles as content tabs (I-7), queried with lambdas named after the model (I-8); every block is backed by docs/examples/inspecting_sql.py and its _annotated twin and runs under the docs harness.
The migration guides get their two sentences: the data-steps page tells a programmatic caller of the migration API that a step's ctx.log lines appear once the application configures logging (the CLI configures it for itself), and the auto-migrate page's sentence about statement records links to the new page.
The API reference carries RenderedSql and REDACTED under their public path, and the ferro.sql logger is named in the Connections guide's logging section with a link to the page.
Acceptance criteria
-
docs/pages/guide/inspecting-sql.mdexists, is in the Guide nav after Raw SQL, has adescription, opens with the what-it-is sentence and a.sql()example before the first heading, and every heading is a noun phrase. - Every Python block on the page is a snippet from
docs/examples/inspecting_sql.pyorinspecting_sql_annotated.py, or a fence marked{test=run prelude=...}; the model declaration appears as Assignment/Annotated tabs; the docs examples test and the docs lint pass over both files and the page. - The page shows a captured record twice: as the one-line message and as the
extraattributes, both produced by running the example, not typed. - The page shows a secret column as
***in a log record and inrendered.params. - The data-steps page carries the programmatic-caller note; the auto-migrate page links to the new page where it mentions statement records; the Connections guide's logging section links to it.
-
RenderedSqlandREDACTEDeach have one API entry under their public path, and the API completeness test passes. -
zensical build --clean --strictpasses.
Files owned
- Create:
docs/pages/guide/inspecting-sql.md,docs/examples/inspecting_sql.py,docs/examples/inspecting_sql_annotated.py - Modify:
zensical.toml,docs/pages/guide/schema/data-steps.md,docs/pages/guide/schema/auto-migrate.md,docs/pages/guide/connections.md,docs/pages/api/queries.md
Interfaces
- Consumes:
ferro.RenderedSql,ferro.REDACTED,Query.<terminal>.sql()from Rendered statement: .sql() on every Query terminal, and the parity pin #766 (shipped in PR feat(query): .sql() on every Query terminal, and the parity pin (#766) #770 onfeat/700-sql-inspection;exists.sql()renders throughrender_count(operation="exists"),update.sqlkeepsupdate()'s two overloaded forms); theferro.sqllogger and record attributes (sql,params,dialect,duration_ms,operation,subject,connection,rows,error) from Statement log: the ferro.sql logger and the Rust emit path, proven on migration DDL #764 (PR feat: statement log records on ferro.sql for migration DDL (#764) #768) and the per-operation names from Statement log: every operation statement, with secrets redacted #765 (PR feat: every operation's statements on the statement log, secrets redacted (#765) #769).docs/pages/api/queries.mdalready carriesRenderedSql,REDACTEDandTerminalentries (added by Rendered statement: .sql() on every Query terminal, and the parity pin #766). - Consumes: the docs harness from Docs rewrite: every snippet runs, every fact matches the code, and the API reference renders cleanly #698 (
tests/test_docs_examples.py,tests/test_docstring_examples.py,tests/_docs_checks.py,docs/examples/_preludes/), and the page conventions indocs/solutions/patterns/docs-page-conventions.md. - Produces: the page
guide/inspecting-sql.md, linked from the Queries, Raw SQL and Connections guides' "see also" pointers; the per-example SQL work in Show captured SQL beside query and mutation examples (needs #700) #725 captures through the sameferro.sqlhandler this page demonstrates.
Test scenarios
- Happy path:
tests/test_docs_examples.pyrunsinspecting_sql.pyand its_annotatedtwin; their printed output matches the page'stextblocks. - Happy path:
tests/test_docs_lint.pyover the page and both examples reports no one-character lambda parameter. - Happy path:
tests/test_docs_site.pyfindsRenderedSqlandREDACTEDunder their public path in the API pages and the nav entry for the page. - Integration:
zensical build --clean --strictpasses with the new page and nav entry.
Verify
uv run --no-sync zensical build --clean --strict
uv run --no-sync pytest tests/test_docs_examples.py tests/test_docs_site.py tests/test_docs_lint.py tests/test_docstring_examples.py -q --no-cov -p no:cacheprovider
uv run --no-sync python -m tests._docs_checks docs/pages/guide/inspecting-sql.md docs/examples/inspecting_sql.py docs/examples/inspecting_sql_annotated.py docs/pages/guide/schema/data-steps.md docs/pages/guide/schema/auto-migrate.md docs/pages/guide/connections.mdBlocked by
- Rendered statement: .sql() on every Query terminal, and the parity pin #766 (
.sql()on everyQueryterminal). - Docs rewrite: every snippet runs, every fact matches the code, and the API reference renders cleanly #698 (the docs rewrite: the harness, preludes and page conventions this page is written against).
Activity
feat: SQL inspection and logging (#700) (#771)