Changelog¶
Auto-included
This page pulls the changelog content directly from the CHANGELOG.md
file at the repository root. Changes are maintained in a single location
and rendered here automatically by MkDocs.
Changelog¶
All notable changes to this project will be documented in this file.
This project adheres to Semantic Versioning.
[2.0.0] - 2026-03-21¶
Added¶
- QueryTurbo: SQL compilation cache with three-phase trust lifecycle
(UNTRUSTED → TRUSTED → POISONED). On cache miss, compiles and caches.
On untrusted hit, validates cached SQL against fresh
as_sql()output and promotes to TRUSTED afterVALIDATION_THRESHOLD(default 3) successful validations. On trusted hit, skipsas_sql()entirely and extracts params directly from the Query tree viaturbo/params.py. On mismatch, poisons the entry for the lifetime of the process (persists across cache clears triggered by migrations). - True SQL Compilation Skipping:
turbo/params.pyextracts params from the Django Query tree without callingas_sql(). Useslookup.as_sql(compiler, connection)per WHERE node for exact param transformations (handles__containswrapping,__isnulldiscarding, etc.) at a fraction of the cost of full SQL compilation. - Prepared Statement Bridge: Multi-database prepared statement support. Automatic protocol-level preparation on PostgreSQL + psycopg3 after a configurable hit-count threshold. Oracle implicit cursor caching. Graceful fallback (TypeError → permanent disable) on unsupported backends.
- AST SerializerMethodField Analyzer: Static analysis of DRF
get_<field>methods usingast.parse()to detect hidden N+1 queries at serialization time. Detects four patterns: related manager access, Model.objects calls, deep attribute chains, and for-loop queryset iteration. - Per-File Analysis:
--fileand--moduleflags oncheck_queriesanddiagnose_projectcommands for focused diagnosis via substring matching. - Benchmark Dashboard:
query_doctor_reportmanagement command generates standalone HTML report with Chart.js graphs showing cache hit rates, top optimized queries, and prepared statement statistics. - GitHub Actions CI Integration:
ci.githubmodule withformat_github_annotations()for inline PR diff annotations,generate_pr_comment()for Markdown PR summaries, andwrite_json_report()for CI consumption. Example workflow inexamples/github-actions/query-doctor.yml. - Baseline Snapshots:
baseline.pywithBaselineSnapshotclass for saving/loading issue snapshots. SHA-256 hashing ignores line numbers for stable identity across code movement.--save-baseline,--baseline, and--fail-on-regressionflags oncheck_queriesanddiagnose_project. - Smart Prescription Grouping:
grouping.pywithgroup_prescriptions()supportingfile_analyzer,root_cause, andviewstrategies.--groupflag oncheck_queriesanddiagnose_project. Console reporter supports grouped output mode. - Async-Safe Context Managers:
turbo_enabled()/turbo_disabled()now usecontextvars.ContextVarinstead ofthreading.local(), making them safe for ASGI deployments with concurrent coroutines. check_serializerscommand: Dedicated management command for AST-based DRF serializer analysis with--app,--file,--format, and--fail-onflags.- Post-migrate cache invalidation: Automatic cache clear on Django
post_migratesignal to prevent stale SQL after schema changes. - Fingerprint collision detection: Cache hit path validates SQL matches and poisons mismatched entries permanently.
__inlookup length in fingerprint: Different__inlist sizes produce different fingerprints, preventing SQL/param count mismatch.select_for_updatein fingerprint: Queries withFOR UPDATE,NOWAIT, andSKIP LOCKEDproduce distinct fingerprints.- Annotation source field fingerprinting: Annotations with the same name but different field targets produce different fingerprints.
Changed¶
- Minimum Python version remains 3.10
- All existing v1.x APIs remain backward compatible
- Version bumped to 2.0.0
- Context managers switched from
threading.local()tocontextvars.ContextVar - Cache entries now track
validated_count,trusted,poisonedstate - New config key:
VALIDATION_THRESHOLD(default 3) controls trust promotion
[1.0.3] - 2026-03-18¶
Fixed¶
- Missing Index analyzer now recommends
Meta.indexeswithmodels.Index()instead ofdb_index=True, following Django's official recommendation since 4.2 (fixes #1) - Auto-fix for missing indexes now generates
Meta.indexessuggestion instead ofdb_index=True _field_is_indexednow checksMeta.constraintsforUniqueConstraint(modern Django 4.2+ pattern) in addition tounique_together
Changed¶
- Full audit of all prescription texts across all 7 analyzers to align with Django 4.2–6.0 best practices
- Fat SELECT prescriptions now mention
.values()/.values_list()as alternatives when model instances aren't needed - N+1 prescriptions for
prefetch_relatednow mentionPrefetch()objects for advanced filtering scenarios - QuerySet evaluation prescriptions now mention
.iterator()for large querysets to reduce memory usage - Updated docs, README, and all affected tests to reflect new recommendation text
[1.0.2] - 2026-03-16¶
Fixed¶
- Fixed SVG terminal renders not displaying on GitHub (switched to absolute URLs)
- Removed Google Fonts @import from SVGs blocked by GitHub CSP
[1.0.1] - 2026-03-15¶
Changed¶
- Added SVG terminal renders to README for visual feature showcase
- Added Django 6.0 mention in README requirements
- Cleaned up committed pycache artifacts
- Updated .gitignore with additional exclusions
[1.0.0] - 2026-03-13¶
Added¶
Core Pipeline¶
- Query interception via
connection.execute_wrapper()— works withoutDEBUG=True - SQL fingerprinting with normalization and SHA-256 hashing
- Source code mapping with file:line references via stack trace analysis
- Django middleware with zero-config setup (one line in
MIDDLEWARE) diagnose_queries()context manager for targeted analysis@diagnoseand@query_budgetdecorators- Full configuration system via
QUERY_DOCTORDjango settings
Analyzers¶
- N+1 Detection — fingerprint-based grouping with FK pattern matching
- Duplicate Query Detection — exact and near-duplicate identification
- Missing Index Detection — WHERE/ORDER BY columns without indexes
- Fat SELECT Detection — flags
SELECT *when fewer columns suffice - QuerySet Evaluation — suggests
.count(),.exists(),.first()alternatives - DRF Serializer N+1 — detects missing prefetch in DRF views
Reporters¶
- Console — Rich terminal output with fallback to plain text
- JSON — structured output for CI/CD pipelines
- Log — Python logging integration
- HTML — standalone dashboard report
- OpenTelemetry — span and event export for observability stacks
Ecosystem¶
- Celery task support via
@diagnose_taskdecorator - Async Django/ASGI middleware support
- Custom analyzer plugin API via Python entry points
- Pytest plugin with
query_doctorfixture check_queriesmanagement command for CI analysisquery_budgetmanagement command for budget enforcement
Project-Wide Diagnosis¶
- diagnose_project management command — crawls all project URLs and generates app-wise health report
- Standalone HTML report with health scores, sortable app scoreboard, and per-URL prescription detail
- JSON report output for CI integration
- Admin dashboard integration showing latest project scan results
Auto-Fix & CI¶
- Auto-Fix Mode —
fix_queriesmanagement command applies diagnosed fixes with dry-run default and .bak backups - Diff-Aware CI —
--diffflag forcheck_queriesto analyze only files changed vs a git ref - .queryignore — project-level file to suppress known false positives by SQL pattern, file, callsite, or issue type
Monitoring¶
- Admin Dashboard — staff-only in-memory dashboard showing recent query diagnosis reports
- Query Complexity Scorer — regex-based SQL complexity analysis flagging excessive JOINs, subqueries, and OR chains
Developer Experience¶
- Every prescription includes severity, description, file:line, and exact code fix
- Zero required dependencies beyond Django
- Optional extras: Rich, Celery, OpenTelemetry
- Full type annotations with
py.typed(PEP 561) - CI matrix: Python 3.10-3.13 x Django 4.2-6.0