SQL Test Case Generator and Coverage Visualizer
DataPilot is a powerful tool that automatically generates test cases for SQL queries and visualizes SQL node coverage. It parses SQL statements using Apache Calcite, extracts table/column information, generates intelligent mock data, and tracks which SQL nodes are covered by the test data.
- SQL Parsing: Parse SQL statements using Apache Calcite with support for extensible SQL dialects
- Metadata Extraction: Automatically extract table names, column names, and WHERE conditions
- Smart Mock Data Generation: Generate realistic test data based on column naming conventions
- Coverage Tracking: Track which SQL nodes are covered by generated test data
- Web Interface: Modern, responsive UI for visualization
- Test Script Export: Generate complete INSERT statements and test scripts
- Java 17+
- Maven 3.6+
mvn spring-boot:runAccess the web interface at: http://localhost:9527
curl -X POST http://localhost:9527/api/analyze \
-H "Content-Type: application/json" \
-d '{
"sql": "SELECT id, name, email FROM users WHERE status = 1",
"rowCount": 5,
"testCaseCount": 1
}'curl http://localhost:9527/api/dialectsDataPilot/
├── parser/ # SQL parsing module
│ ├── SqlDialectProvider.java # Dialect interface (extensible)
│ ├── StandardSqlDialectProvider.java
│ ├── SqlParserService.java # Core parsing service
│ └── SqlNodeVisitor.java # SqlNode traverser
│
├── generator/ # Test data generation module
│ ├── DataType.java # Data type definition and inference
│ ├── TableSchema.java # Table structure definition
│ ├── MockDataGenerator.java # Mock data generator
│ └── TestCase.java # Test case model
│
├── coverage/ # Coverage tracking module
│ ├── CoverageNode.java # Coverage node model
│ ├── CoverageResult.java # Coverage result
│ └── CoverageTracker.java # Coverage tracker
│
└── controller/ # Web API
└── DataPilotController.java
DataPilot intelligently infers data types based on column naming conventions:
| Column Pattern | Inferred Type | Example |
|---|---|---|
*_id, id |
BIGINT | user_id → 1, 2, 3 |
*_name, name |
VARCHAR(100) | user_name → "张伟", "李芳" |
*_email, email |
VARCHAR(100) | email → "[email protected]" |
*_phone, *_mobile |
VARCHAR(20) | mobile → "13812345678" |
*_amount, *_price |
DECIMAL(15,2) | amount → 1234.56 |
*_date |
DATE | order_date → "2024-01-15" |
*_at, *_time |
TIMESTAMP | created_at → "2024-01-15 10:30:00" |
is_*, has_* |
BOOLEAN | is_active → true/false |
*_status, *_type |
INTEGER | status → 0, 1, 2, 3 |
{
"success": true,
"parseResult": {
"originalSql": "SELECT id, name FROM users WHERE status = 1",
"dialect": "STANDARD",
"tableNames": ["users"],
"columns": [
{"columnName": "id"},
{"columnName": "name"}
]
},
"testCases": [{
"tableDataMap": {
"users": {
"columns": ["id", "name"],
"rows": [
{"id": 1, "name": "张伟"},
{"id": 2, "name": "李芳"}
]
}
}
}],
"coverageResult": {
"coveragePercentage": 100.0,
"allNodes": [...],
"coveredNodeIds": [...]
},
"testScript": "-- Test Case for SQL:\nINSERT INTO users..."
}Implement SqlDialectProvider to add support for custom SQL dialects:
@Component
public class MySqlDialectProvider implements SqlDialectProvider {
@Override
public String getDialectName() {
return "MYSQL";
}
@Override
public SqlNode parse(String sql) throws SqlParseException {
SqlParser.Config config = SqlParser.config()
.withLex(Lex.MYSQL);
return SqlParser.create(sql, config).parseQuery();
}
}- Java 17
- Spring Boot 3.2
- Apache Calcite 1.36 - SQL parsing
- Thymeleaf - Server-side templating
- Lombok - Boilerplate reduction
MIT License
