# Query Validation Examples
This document demonstrates the PostgreSQL MCP Server's intelligent query validation across different scenarios.
## β
Good Queries - Best Practices
### Example 1: Well-Optimized Analytics Query
```json
{
"name": "validate_query",
"arguments": {
"sql": "SELECT DATE(created_at) as order_date, COUNT(*) as order_count, SUM(total_amount) as daily_revenue FROM orders WHERE created_at >= '2024-01-01' AND status = 'delivered' GROUP BY DATE(created_at) ORDER BY order_date DESC LIMIT 30",
"schema": "public"
}
}
```
**Validation Result:**
```
Query Analysis Report
==================================================
Valid: β
Yes
Complexity: 4/10
π‘ Optimization Suggestions:
1. Run EXPLAIN ANALYZE to see the actual execution plan
2. Consider adding an index on orders.created_at if queries are slow
3. For ORDER BY with LIMIT, ensure there's an index on the ORDER BY columns
```
**Why this is good:**
- β
Uses specific columns instead of SELECT *
- β
Includes proper date range filtering
- β
Has a LIMIT clause to prevent large result sets
- β
Uses indexed columns in WHERE clause
---
### Example 2: Efficient Customer Lookup
```json
{
"name": "validate_query",
"arguments": {
"sql": "SELECT id, email, first_name, last_name, created_at FROM users WHERE email = $1 AND is_active = true",
"schema": "public"
}
}
```
**Validation Result:**
```
Query Analysis Report
==================================================
Valid: β
Yes
Complexity: 1/10
π‘ Optimization Suggestions:
1. Run EXPLAIN ANALYZE to see the actual execution plan
```
**Why this is good:**
- β
Uses parameterized queries ($1) for security
- β
Selects only needed columns
- β
Uses indexed columns (email)
- β
Includes status filtering
---
## β οΈ Queries with Performance Warnings
### Example 3: Inefficient SELECT * Query
```json
{
"name": "validate_query",
"arguments": {
"sql": "SELECT * FROM orders WHERE user_id = 123",
"schema": "public"
}
}
```
**Validation Result:**
```
Query Analysis Report
==================================================
Valid: β
Yes
Complexity: 2/10
β‘ Performance Warnings:
WARNING: SELECT * can be inefficient
π‘ Specify only needed columns instead of using SELECT *
INFO: Consider adding LIMIT clause
π‘ Add LIMIT clause to prevent large result sets
π‘ Optimization Suggestions:
1. Run EXPLAIN ANALYZE to see the actual execution plan
2. Consider adding an index on orders.user_id if queries are slow
```
**How to improve:**
```sql
-- Better version:
SELECT id, order_number, total_amount, status, created_at
FROM orders
WHERE user_id = $1
ORDER BY created_at DESC
LIMIT 50
```
---
### Example 4: Leading Wildcard in LIKE
```json
{
"name": "validate_query",
"arguments": {
"sql": "SELECT name, email FROM users WHERE email LIKE '%@gmail.com' ORDER BY created_at DESC",
"schema": "public"
}
}
```
**Validation Result:**
```
Query Analysis Report
==================================================
Valid: β
Yes
Complexity: 3/10
β‘ Performance Warnings:
WARNING: LIKE with leading wildcard prevents index usage
π‘ Avoid leading wildcards in LIKE patterns or consider full-text search
INFO: Consider adding LIMIT clause
π‘ Add LIMIT clause to prevent large result sets
π‘ Optimization Suggestions:
1. Run EXPLAIN ANALYZE to see the actual execution plan
2. For ORDER BY with LIMIT, ensure there's an index on the ORDER BY columns
```
**How to improve:**
```sql
-- Better approach using domain extraction:
SELECT name, email
FROM users
WHERE email LIKE '%gmail.com' -- Still not ideal, but better
OR email ~ '@gmail\.com$' -- Use regex for end-of-string match
ORDER BY created_at DESC
LIMIT 100
```
---
### Example 5: Cartesian Product Risk
```json
{
"name": "validate_query",
"arguments": {
"sql": "SELECT u.name, p.name, o.total_amount FROM users u, products p, orders o WHERE u.is_active = true",
"schema": "public"
}
}
```
**Validation Result:**
```
Query Analysis Report
==================================================
Valid: β
Yes
Complexity: 5/10
β‘ Performance Warnings:
WARNING: Potential cartesian product detected
π‘ Ensure JOIN clauses have proper ON conditions
WARNING: SELECT * can be inefficient
π‘ Specify only needed columns instead of using SELECT *
π‘ Optimization Suggestions:
1. Run EXPLAIN ANALYZE to see the actual execution plan
2. For complex JOINs, consider the join order - start with the most selective table
```
**How to fix:**
```sql
-- Correct version with proper JOINs:
SELECT u.first_name, u.last_name, p.name as product_name, o.total_amount
FROM users u
JOIN orders o ON u.id = o.user_id
JOIN order_items oi ON o.id = oi.order_id
JOIN products p ON oi.product_id = p.id
WHERE u.is_active = true
LIMIT 100
```
---
## π Security Issues - Blocked Queries
### Example 6: SQL Injection Attempt
```json
{
"name": "validate_query",
"arguments": {
"sql": "SELECT * FROM users WHERE id = 1; DROP TABLE users; --",
"schema": "public"
}
}
```
**Validation Result:**
```
Query Analysis Report
==================================================
Valid: β No
Complexity: 10/10
π Security Issues:
CRITICAL: Only SELECT statements are allowed
π‘ Use SELECT queries for data retrieval only
WARNING: Potential SQL injection with dangerous commands
π‘ Use parameterized queries instead
WARNING: SQL comments can be used to bypass security
π‘ Use parameterized queries instead
β‘ Performance Warnings:
WARNING: SELECT * can be inefficient
π‘ Specify only needed columns instead of using SELECT *
```
**Why this is blocked:**
- β Contains dangerous DROP statement
- β Uses SQL injection techniques
- β Has malicious SQL comments
---
### Example 7: Dangerous System Functions
```json
{
"name": "validate_query",
"arguments": {
"sql": "SELECT pg_read_file('/etc/passwd') as file_content",
"schema": "public"
}
}
```
**Validation Result:**
```
Query Analysis Report
==================================================
Valid: β No
Complexity: 8/10
π Security Issues:
CRITICAL: Dangerous function 'pg_read_file' detected
π‘ Remove dangerous system functions
π‘ Optimization Suggestions:
1. Run EXPLAIN ANALYZE to see the actual execution plan
```
**Why this is blocked:**
- β Uses dangerous PostgreSQL system function
- β Could expose sensitive server information
- β Violates security boundaries
---
### Example 8: Non-SELECT Statement
```json
{
"name": "validate_query",
"arguments": {
"sql": "UPDATE users SET email = 'hacker@evil.com' WHERE id = 1",
"schema": "public"
}
}
```
**Validation Result:**
```
Query Analysis Report
==================================================
Valid: β No
Complexity: 10/10
π Security Issues:
CRITICAL: Only SELECT statements are allowed
π‘ Use SELECT queries for data retrieval only
π‘ Optimization Suggestions:
1. Run EXPLAIN ANALYZE to see the actual execution plan
```
**Why this is blocked:**
- β UPDATE statement not allowed (read-only policy)
- β Could modify data unexpectedly
- β Violates MCP server security model
---
## π§ Complex Queries with Optimization Suggestions
### Example 9: High-Complexity Analytics Query
```json
{
"name": "validate_query",
"arguments": {
"sql": "WITH monthly_sales AS (SELECT DATE_TRUNC('month', o.created_at) as month, SUM(o.total_amount) as revenue, COUNT(*) as order_count FROM orders o WHERE o.status = 'delivered' GROUP BY DATE_TRUNC('month', o.created_at)), category_performance AS (SELECT c.name as category, SUM(oi.total_price) as category_revenue FROM order_items oi JOIN products p ON oi.product_id = p.id JOIN categories c ON p.category_id = c.id JOIN orders o ON oi.order_id = o.id WHERE o.status = 'delivered' GROUP BY c.id, c.name) SELECT ms.month, ms.revenue, ms.order_count, cp.category, cp.category_revenue FROM monthly_sales ms CROSS JOIN category_performance cp ORDER BY ms.month DESC, cp.category_revenue DESC",
"schema": "public"
}
}
```
**Validation Result:**
```
Query Analysis Report
==================================================
Valid: β
Yes
Complexity: 9/10
β‘ Performance Warnings:
INFO: Consider adding LIMIT clause
π‘ Add LIMIT clause to prevent large result sets
π‘ Optimization Suggestions:
1. Run EXPLAIN ANALYZE to see the actual execution plan
2. Consider adding an index on orders.user_id if queries are slow
3. For complex JOINs, consider the join order - start with the most selective table
4. For ORDER BY with LIMIT, ensure there's an index on the ORDER BY columns
```
**Optimization notes:**
- β οΈ Very complex query (9/10 complexity)
- π‘ Consider breaking into smaller queries
- π‘ Add appropriate indexes for date-based filtering
- π‘ Consider materialized views for frequently-run analytics
---
## π Summary of Validation Categories
| Category | Count | Description |
|----------|-------|-------------|
| β
**Good Queries** | 2 | Well-optimized, secure, efficient |
| β οΈ **Performance Warnings** | 4 | Valid but with optimization opportunities |
| π **Security Blocked** | 3 | Dangerous queries that are prevented |
| π§ **High Complexity** | 1 | Valid but computationally expensive |
## π‘ Key Takeaways
1. **Always use parameterized queries** to prevent SQL injection
2. **Specify exact columns** instead of SELECT *
3. **Include LIMIT clauses** to prevent large result sets
4. **Use proper JOIN syntax** to avoid cartesian products
5. **Leverage indexes** by filtering on indexed columns
6. **Avoid leading wildcards** in LIKE patterns
7. **Only SELECT statements** are allowed for security
The MCP server helps you write better, safer, and more performant SQL queries! π