QueryTuner logo

# QueryTuner β€” AI-Powered SQL Query Diagnostics [![Version](https://img.shields.io/badge/version-0.2.0-blue)](CHANGELOG.md) [![Backend](https://img.shields.io/badge/backend-FastAPI-009688?logo=fastapi)](https://api.querytuner.com/docs) [![Frontend](https://img.shields.io/badge/frontend-React-61DAFB?logo=react)](https://querytuner.com) [![AI](https://img.shields.io/badge/AI-HuggingFace%20%7C%20OpenAI-FFD21F?logo=huggingface)](https://huggingface.co) [![License](https://img.shields.io/badge/license-MIT-blue)](LICENSE) [![Status](https://img.shields.io/badge/status-live-brightgreen)](https://querytuner.com) > Only 0.3% of developers are database administrators.
> The SQL performance tools that exist were built for them.
> QueryTuner is for the other 99.7%. > > *β€” Stack Overflow Developer Survey 2024, 65,000+ developers* **No database connection required. Paste-in and analyze.** πŸ”— **Live Demo β†’ [querytuner.com](https://querytuner.com)** πŸ“– **API Docs β†’ [/docs](https://api.querytuner.com/docs)** --- ## What It Does QueryTuner analyzes SQL queries in two layers: 1. **Heuristic Engine** (always on, instant) β€” rule-based detection of common performance anti-patterns: missing indexes, leading wildcards, functions in WHERE clauses, SELECT *, unbounded ORDER BY, and more. 2. **AI Layer** (optional) β€” powered by HuggingFace (`Qwen/Qwen2.5-Coder`) or OpenAI (`gpt-4o-mini`). Generates CTE rewrites, CREATE INDEX statements with justification, and plain-English diagnosis. --- ## Features - πŸ—„οΈ **5 Database Dialects** β€” PostgreSQL, MySQL, Oracle, SQL Server, SQLite - ⚑ **Heuristic Engine** β€” 12 deterministic rules, always available, no external API calls required - πŸ—‚οΈ **Schema-Aware Analysis** β€” paste `CREATE TABLE` DDL and index recommendations upgrade from estimated to **confirmed**, resolved against your real table and column names - πŸ”§ **Dialect-Correct Index DDL** β€” `CREATE INDEX CONCURRENTLY` (PostgreSQL), `ALTER TABLE ... ADD INDEX` (MySQL), `NOLOGGING` (Oracle), `WITH (ONLINE=ON)` (SQL Server) - πŸ€– **Dual AI Provider** β€” HuggingFace (default, free) or OpenAI, with structured JSON output (falls back to readable plain text if the model doesn't return JSON) - πŸ” **Severity-Ranked Findings** β€” Critical β†’ High β†’ Medium β†’ Low - πŸ“‹ **Optimized Query Output** β€” rewritten SQL you can copy and run - πŸ”— **Shareable Reports** β€” every analysis gets a permanent `/report/:id` URL - πŸ“ˆ **Analytics** β€” Google Analytics 4 event tracking on every user action - πŸ›‘οΈ **Security Scanning** β€” detects SQL injection patterns and unsafe constructs - πŸ“Š **Readability Score** β€” quantifies query clarity for code review - πŸ”’ **Client-side query sanitizer** β€” replace proprietary table and column names with dummy values before analysis runs. Your real schema names never leave your browser. One click restores original names in DDL output after analysis. Substitution map lives in browser memory only β€” gone on page refresh, never persisted. - πŸ”Œ **REST API** β€” integrable into CI/CD pipelines and developer tooling - 🚫 **No DB Connection Needed** β€” works entirely from pasted query text (schema DDL is optional, only needed to unlock confirmed mode) --- ## Live API ```bash # Analyze a query (heuristics only, no API key needed) curl -X POST https://api.querytuner.com/analyze \ -H "Content-Type: application/json" \ -d '{ "query": "SELECT * FROM orders WHERE customer_id = 42 ORDER BY created_at DESC", "db_type": "postgresql", "use_llm": false }' # With AI insights (requires HF_API_KEY on server) curl -X POST https://api.querytuner.com/analyze \ -H "Content-Type: application/json" \ -d '{ "query": "SELECT u.id, COUNT(o.id) FROM users u LEFT JOIN orders o ON o.user_id = u.id WHERE YEAR(o.created_at) = 2025 GROUP BY u.id", "db_type": "mysql", "use_llm": true, "llm_provider": "huggingface" }' ``` **Supported `db_type` values:** `postgresql` Β· `mysql` Β· `oracle` Β· `sqlserver` Β· `sqlite` **Supported `llm_provider` values:** `huggingface` Β· `openai` ### Example Response ```json { "optimization_suggestions": [ { "type": "function_in_where", "severity": "high", "suggestion": "Avoid wrapping filtered columns in functions inside WHERE", "reason": "YEAR(created_at) prevents index usage on the created_at column", "estimated_improvement": "High β€” use range condition instead" } ], "ai_insights": "...", "optimized_query": "...", "readability_score": 83.5, "analysis_time_ms": 5.4, "used_ai": true, "ai_model": "Qwen/Qwen2.5-Coder-3B-Instruct" } ``` Full schema at [`/docs`](https://api.querytuner.com/docs). --- ## Architecture ``` querytuner.com (Vercel) api.querytuner.com (Render) β”‚ β”‚ β”‚ POST /analyze β”‚ └─────────────────────────────────────────►│ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ FastAPI + SQLAnalyzer β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Heuristic Engine β”‚ β”‚ ← always runs β”‚ β”‚ (query_parser.py) β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ LLM Router β”‚ β”‚ ← optional β”‚ β”‚ HuggingFaceβ”‚OpenAIβ”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` **Stack:** - Backend: Python Β· FastAPI Β· Pydantic Β· sqlparse Β· LangChain - Frontend: React Β· Tailwind CSS Β· Axios Β· Lucide Icons - AI: HuggingFace Inference API (`Qwen/Qwen2.5-Coder-3B-Instruct`) Β· OpenAI-compatible - Deploy: Render (backend) Β· Vercel (frontend) --- ## Run Locally **Prerequisites:** Python 3.11+, Node.js 18+ ```bash # Clone git clone https://github.com/AutoShiftOps/querytuner cd querytuner # Backend cd backend python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate pip install -r requirements.txt cp .env.example .env # add your HF_API_KEY uvicorn app.main:app --reload --port 8000 # Frontend (new terminal) cd frontend npm install echo "VITE_API_URL=http://localhost:8000" > .env.local npm run dev ``` Open `http://localhost:3000` (this project pins Vite's dev server port in `vite.config.js`; it does not use Vite's default 5173) --- ## Environment Variables | Variable | Required | Default | Description | |---|---|---|---| | `HF_API_KEY` | Yes (for AI) | β€” | HuggingFace API key | | `HF_MODEL` | No | `Qwen/Qwen2.5-Coder-3B-Instruct` | HuggingFace model ID | | `OPENAI_API_KEY` | No | β€” | Enables OpenAI provider | | `OPENAI_MODEL` | No | `gpt-4o-mini` | OpenAI model to use | | `DEFAULT_LLM_PROVIDER` | No | `huggingface` | Default AI provider | | `AI_MAX_TOKENS` | No | `800` | Max tokens per LLM response | | `MAX_QUERY_CHARS` | No | `20000` | Max query input size | | `SUPABASE_URL` | No | β€” | Supabase project URL β€” enables shareable report URLs | | `SUPABASE_ANON_KEY` | No | β€” | Supabase anon key β€” enables analysis persistence | Create a `.env` file in `/backend` using `.env.example` as the template. --- ## Project Structure ``` sql-query-analyzer/ β”œβ”€β”€ backend/ β”‚ β”œβ”€β”€ app/ β”‚ β”‚ β”œβ”€β”€ agents/ β”‚ β”‚ β”‚ β”œβ”€β”€ sql_analyzer.py # Main analyzer agent (heuristics + LLM orchestration) β”‚ β”‚ β”‚ β”œβ”€β”€ optimizer.py # Query rewrite engine β”‚ β”‚ β”‚ └── explainer.py # Plain-English explanation layer β”‚ β”‚ β”œβ”€β”€ llm/ β”‚ β”‚ β”‚ β”œβ”€β”€ hf_client.py # HuggingFace async client β”‚ β”‚ β”‚ └── router.py # Dual-provider LLM router (HF + OpenAI) β”‚ β”‚ β”œβ”€β”€ schemas/ β”‚ β”‚ β”‚ └── models.py # Pydantic request/response models β”‚ β”‚ β”œβ”€β”€ tools/ β”‚ β”‚ β”‚ β”œβ”€β”€ query_parser.py # SQL structure extractor + heuristic rules β”‚ β”‚ β”‚ β”œβ”€β”€ execution_planner.py β”‚ β”‚ β”‚ └── index_recommender.py β”‚ β”‚ β”œβ”€β”€ utils/ β”‚ β”‚ β”‚ β”œβ”€β”€ config.py β”‚ β”‚ β”‚ β”œβ”€β”€ database.py # Supabase persistence β€” save/fetch analyses β”‚ β”‚ β”‚ β”œβ”€β”€ dialect_config.py # Dialect-specific DDL, rewrites, LLM prompts (Phase 1.7) β”‚ β”‚ β”‚ └── db_connectors.py β”‚ β”‚ └── main.py # FastAPI app, routes, rate limiting β”‚ β”œβ”€β”€ migrations/ # Versioned Supabase schema (001_initial_schema.sql, ...) β”‚ β”œβ”€β”€ LIMITATIONS.md # Known gaps and scope boundaries β”‚ β”œβ”€β”€ requirements.txt β”‚ └── Dockerfile β”œβ”€β”€ frontend/ β”‚ β”œβ”€β”€ src/ β”‚ β”‚ β”œβ”€β”€ components/ β”‚ β”‚ β”‚ β”œβ”€β”€ QueryInput.jsx β”‚ β”‚ β”‚ β”œβ”€β”€ OptimizationSuggestions.jsx β”‚ β”‚ β”‚ β”œβ”€β”€ ExecutionPlan.jsx β”‚ β”‚ β”‚ β”œβ”€β”€ ResultsPanel.jsx β”‚ β”‚ β”‚ β”œβ”€β”€ SampleQueries.jsx # Pre-built example queries β”‚ β”‚ β”‚ β”œβ”€β”€ Header.jsx # Sticky enterprise nav β”‚ β”‚ β”‚ β”œβ”€β”€ Hero.jsx # Value proposition strip β”‚ β”‚ β”‚ β”œβ”€β”€ Footer.jsx # Links + attribution β”‚ β”‚ β”‚ β”œβ”€β”€ Toast.jsx # Notification system β”‚ β”‚ β”‚ β”œβ”€β”€ ShareButton.jsx # Share analysis URL β”‚ β”‚ β”‚ β”œβ”€β”€ QueryDiagnosis.jsx # Structured plain-explanation renderer β”‚ β”‚ β”‚ β”œβ”€β”€ ReportPage.jsx # Shareable /report/:id read-only page β”‚ β”‚ β”‚ └── SanitizerPanel.jsx # Three-state sanitizer UI β”‚ β”‚ β”œβ”€β”€ utils/ β”‚ β”‚ β”‚ β”œβ”€β”€ analytics.js # GA4 event tracking β”‚ β”‚ β”‚ β”œβ”€β”€ aiInsights.js # Shared AI-JSON parsing (App.jsx + ResultsPanel.jsx) β”‚ β”‚ β”‚ └── sanitizer.js # Client-side query sanitizer (substitution map, β”‚ β”‚ β”‚ # sanitize/desanitize/buildDiff) β”‚ β”‚ └── App.jsx β”‚ └── package.json β”œβ”€β”€ docs/ β”œβ”€β”€ CHANGELOG.md └── .github/workflows/ ``` --- ## Roadmap * [x] Core heuristic engine β€” 12 rules across 5 dialects β€” Phase 1 βœ… * [x] Persistent query history (Supabase) β€” Phase 1.5 βœ… * [x] Shareable /report/:id URLs β€” Phase 1.5 βœ… * [x] Enterprise UI shell (Header, Hero, Footer, Toast) β€” Phase 1.6 βœ… * [x] Google Analytics 4 event tracking β€” Phase 1.6 βœ… * [x] Dialect-aware DDL, rewrites, and LLM prompts (5 DB types) β€” Phase 1.7 βœ… * [x] Schema-aware analysis β€” paste DDL for confirmed (not just estimated) index suggestions β€” Phase 2 βœ… * [ ] LangGraph agentic pipeline β€” Phase 3 ⏭ (deferred post-revenue) * [ ] API key auth + usage metering β€” Phase 4 πŸ”œ * [ ] Stripe payments β€” Free / Pro / Team tiers β€” Phase 4 πŸ”œ * [ ] GitHub Action: `querytuner-analyze` for CI/CD pipelines β€” Phase 5 πŸ”œ * [ ] Cross-database execution plan risk normalizer (UEPN) β€” Phase 5 πŸ”œ * [ ] Live DB connection mode β€” Phase 5 πŸ”œ --- ## Known Limitations See [LIMITATIONS.md](backend/LIMITATIONS.md) for the full list. Key limitations: no live DB connection, stateless analysis (no query history across runs), LLM availability depends on the HuggingFace free tier, and LATERAL join correlated-column detection is not yet supported. --- ## Contributing Issues and PRs welcome. Please open an issue before submitting a large change. ```bash git checkout -b feature/your-feature # make changes, add tests git commit -m "feat: describe your change" git push origin feature/your-feature # open a pull request ``` --- ## License MIT Β© 2026 [AutoShiftOps](https://github.com/AutoShiftOps) Built by [Sudhakar Sajja](https://github.com/AutoShiftOps) β€” Application Architect, TechMahindra