Initial commit: Sistema Autoparts DB
- Base de datos SQLite con información de vehículos - Dashboard web con Flask y Bootstrap - Scripts de web scraping para RockAuto - Interfaz CLI para consultas - Documentación completa del proyecto Incluye: - 12 marcas de vehículos - 10,923 modelos - 10,919 especificaciones de motores - 12,075 combinaciones modelo-año-motor
This commit is contained in:
82
vehicle_database/GETTING_STARTED.md
Normal file
82
vehicle_database/GETTING_STARTED.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Vehicle Database - Getting Started Guide
|
||||
|
||||
## Overview
|
||||
This project provides a comprehensive database system for storing information about vehicle brands, models, years, and engines. The database is built using SQLite and managed through Python scripts.
|
||||
|
||||
## Database Structure
|
||||
The database consists of five main tables:
|
||||
- **brands**: Vehicle manufacturers (Toyota, Ford, etc.)
|
||||
- **models**: Vehicle models (Camry, F-150, etc.)
|
||||
- **engines**: Engine specifications (2JZ-GTE, EcoBoost, etc.)
|
||||
- **years**: Calendar years for vehicle production
|
||||
- **model_year_engine**: Junction table linking all entities with trim levels and specifications
|
||||
|
||||
## Setup and Usage
|
||||
|
||||
### 1. Initial Setup
|
||||
Run the setup script to initialize the database:
|
||||
```bash
|
||||
cd vehicle_database
|
||||
./setup.sh
|
||||
```
|
||||
|
||||
### 2. Querying the Database
|
||||
Use the interactive query interface:
|
||||
```bash
|
||||
python3 scripts/query_interface.py
|
||||
```
|
||||
|
||||
The query interface allows you to:
|
||||
- Search for vehicles by brand, model, year, or engine
|
||||
- Browse all available brands
|
||||
- View models for specific brands
|
||||
- See production years for specific models
|
||||
|
||||
### 3. Managing the Database
|
||||
Use the database manager for programmatic access:
|
||||
```bash
|
||||
python3 scripts/database_manager.py
|
||||
```
|
||||
|
||||
### 4. Importing Data
|
||||
To import data from CSV files:
|
||||
1. Prepare your data in the required CSV format
|
||||
2. Use the CSV importer functionality in your own scripts
|
||||
|
||||
Sample CSV files are provided in the `data/` directory.
|
||||
|
||||
## Example Queries
|
||||
|
||||
The system supports various search options:
|
||||
- Find all vehicles by a specific brand
|
||||
- Search for a specific model across all years
|
||||
- Filter by engine type or specifications
|
||||
- Look up trim levels and drivetrain configurations
|
||||
|
||||
## Extending the Database
|
||||
|
||||
To add more data:
|
||||
1. Use the Python API in `scripts/database_manager.py`
|
||||
2. Directly execute SQL commands on the SQLite database
|
||||
3. Import data from CSV files using the structure provided
|
||||
|
||||
## File Structure
|
||||
```
|
||||
vehicle_database/
|
||||
├── sql/
|
||||
│ └── schema.sql # Database schema
|
||||
├── scripts/
|
||||
│ ├── database_manager.py # Main database manager
|
||||
│ ├── query_interface.py # Interactive query interface
|
||||
│ └── csv_importer.py # CSV import functionality
|
||||
├── data/ # Sample CSV data files
|
||||
├── vehicle_database.db # SQLite database file
|
||||
├── setup.sh # Setup script
|
||||
└── README.md # Project documentation
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
1. Explore the database using the query interface
|
||||
2. Add your own vehicle data
|
||||
3. Customize the schema if needed for your specific requirements
|
||||
4. Extend the Python scripts with additional functionality
|
||||
106
vehicle_database/README.md
Normal file
106
vehicle_database/README.md
Normal file
@@ -0,0 +1,106 @@
|
||||
# Vehicle Database
|
||||
|
||||
A comprehensive database system for storing information about vehicle brands, models, years, and engines.
|
||||
|
||||
## Overview
|
||||
|
||||
This project provides a structured database for vehicle information with the following entities:
|
||||
|
||||
- **Brands**: Vehicle manufacturers with details like country of origin and founding year
|
||||
- **Models**: Vehicle models with body type, generation, and production years
|
||||
- **Years**: Calendar years for vehicle production
|
||||
- **Engines**: Engine specifications including displacement, cylinders, power, and fuel type
|
||||
- **Model-Year-Engine**: Junction table linking all entities with trim levels and specifications
|
||||
|
||||
## Database Schema
|
||||
|
||||
The database uses SQLite and consists of the following tables:
|
||||
|
||||
### `brands`
|
||||
- `id`: Primary key
|
||||
- `name`: Brand name (e.g., Toyota, Ford)
|
||||
- `country`: Country of origin
|
||||
- `founded_year`: Year the company was founded
|
||||
|
||||
### `engines`
|
||||
- `id`: Primary key
|
||||
- `name`: Engine name
|
||||
- `displacement_cc`: Engine displacement in cubic centimeters
|
||||
- `cylinders`: Number of cylinders
|
||||
- `fuel_type`: Type of fuel (gasoline, diesel, electric, hybrid)
|
||||
- `power_hp`: Horsepower
|
||||
- `torque_nm`: Torque in Newton meters
|
||||
- `engine_code`: Manufacturer engine code
|
||||
|
||||
### `models`
|
||||
- `id`: Primary key
|
||||
- `brand_id`: Foreign key to brands table
|
||||
- `name`: Model name (e.g., Camry, Civic)
|
||||
- `body_type`: Body style (sedan, SUV, truck, etc.)
|
||||
- `generation`: Model generation
|
||||
- `production_start_year`: Year production started
|
||||
- `production_end_year`: Year production ended (NULL if still in production)
|
||||
|
||||
### `years`
|
||||
- `id`: Primary key
|
||||
- `year`: Calendar year
|
||||
|
||||
### `model_year_engine`
|
||||
- `id`: Primary key
|
||||
- `model_id`: Foreign key to models table
|
||||
- `year_id`: Foreign key to years table
|
||||
- `engine_id`: Foreign key to engines table
|
||||
- `trim_level`: Trim level (e.g., base, luxury, sport)
|
||||
- `drivetrain`: Drive system (FWD, RWD, AWD, 4WD)
|
||||
- `transmission`: Transmission type (manual, automatic, CVT)
|
||||
|
||||
## Setup
|
||||
|
||||
1. Install Python 3.x if not already installed
|
||||
2. Clone or download this repository
|
||||
3. Run the database manager script:
|
||||
|
||||
```bash
|
||||
cd vehicle_database
|
||||
python scripts/database_manager.py
|
||||
```
|
||||
|
||||
This will create the database, populate it with sample data, and run example queries.
|
||||
|
||||
## Usage
|
||||
|
||||
The `VehicleDatabaseManager` class provides methods to:
|
||||
|
||||
- Create and manage the database schema
|
||||
- Insert new brands, models, engines, and years
|
||||
- Query vehicle information
|
||||
- Link models, years, and engines with trim levels and specifications
|
||||
|
||||
## Sample Queries
|
||||
|
||||
The script demonstrates several query patterns:
|
||||
|
||||
- Get all brands
|
||||
- Get models for a specific brand
|
||||
- Search for specific vehicles by brand, model, year, or engine
|
||||
- Retrieve comprehensive vehicle information
|
||||
|
||||
## Extending the Database
|
||||
|
||||
To add more data, you can:
|
||||
|
||||
1. Use the provided Python API
|
||||
2. Directly execute SQL commands on the SQLite database
|
||||
3. Import data from CSV files using the provided structure
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
vehicle_database/
|
||||
├── sql/
|
||||
│ └── schema.sql # Database schema
|
||||
├── scripts/
|
||||
│ └── database_manager.py # Python database manager
|
||||
├── data/ # Directory for data files
|
||||
└── README.md # This file
|
||||
```
|
||||
6
vehicle_database/data/brands.csv
Normal file
6
vehicle_database/data/brands.csv
Normal file
@@ -0,0 +1,6 @@
|
||||
name,country,founded_year
|
||||
Mercedes-Benz,Germany,1926
|
||||
Audi,Germany,1909
|
||||
Nissan,Japan,1933
|
||||
Chevrolet,USA,1911
|
||||
Volkswagen,Germany,1937
|
||||
|
5
vehicle_database/data/engines.csv
Normal file
5
vehicle_database/data/engines.csv
Normal file
@@ -0,0 +1,5 @@
|
||||
name,displacement_cc,cylinders,fuel_type,power_hp,torque_nm,engine_code
|
||||
VQ35DE,3500,6,gasoline,280,260,VQ35DE
|
||||
LS3,6200,8,gasoline,430,424,LS3
|
||||
EA888,2000,4,gasoline,228,258,EA888
|
||||
M274,2000,4,gasoline,241,273,M274
|
||||
|
5
vehicle_database/data/models.csv
Normal file
5
vehicle_database/data/models.csv
Normal file
@@ -0,0 +1,5 @@
|
||||
brand_name,name,body_type,generation,production_start_year,production_end_year
|
||||
Toyota,Corolla,sedan,E210,2018,
|
||||
Honda,Accord,sedan,X,2018,
|
||||
Ford,F-150,truck,13th Gen,2015,
|
||||
BMW,3 Series,sedan,G20,2018,
|
||||
|
152
vehicle_database/scripts/csv_importer.py
Normal file
152
vehicle_database/scripts/csv_importer.py
Normal file
@@ -0,0 +1,152 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
CSV Import Script for Vehicle Database
|
||||
This script allows importing vehicle data from CSV files
|
||||
"""
|
||||
|
||||
import csv
|
||||
import sqlite3
|
||||
import os
|
||||
from typing import Dict, List
|
||||
|
||||
|
||||
class CSVImporter:
|
||||
def __init__(self, db_path: str = "vehicle_database.db"):
|
||||
self.db_path = db_path
|
||||
|
||||
def import_brands_from_csv(self, csv_file: str):
|
||||
"""Import brands from a CSV file"""
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
with open(csv_file, 'r', newline='', encoding='utf-8') as file:
|
||||
reader = csv.DictReader(file)
|
||||
for row in reader:
|
||||
cursor.execute(
|
||||
"INSERT OR IGNORE INTO brands (name, country, founded_year) VALUES (?, ?, ?)",
|
||||
(row['name'], row.get('country'), row.get('founded_year'))
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
print(f"Imported brands from {csv_file}")
|
||||
|
||||
def import_engines_from_csv(self, csv_file: str):
|
||||
"""Import engines from a CSV file"""
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
with open(csv_file, 'r', newline='', encoding='utf-8') as file:
|
||||
reader = csv.DictReader(file)
|
||||
for row in reader:
|
||||
cursor.execute(
|
||||
"""INSERT OR IGNORE INTO engines
|
||||
(name, displacement_cc, cylinders, fuel_type, power_hp, torque_nm, engine_code)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)""",
|
||||
(
|
||||
row['name'],
|
||||
row.get('displacement_cc'),
|
||||
row.get('cylinders'),
|
||||
row.get('fuel_type'),
|
||||
row.get('power_hp'),
|
||||
row.get('torque_nm'),
|
||||
row.get('engine_code')
|
||||
)
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
print(f"Imported engines from {csv_file}")
|
||||
|
||||
def import_models_from_csv(self, csv_file: str):
|
||||
"""Import models from a CSV file"""
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
with open(csv_file, 'r', newline='', encoding='utf-8') as file:
|
||||
reader = csv.DictReader(file)
|
||||
|
||||
# First, create a mapping of brand names to IDs
|
||||
cursor.execute("SELECT id, name FROM brands")
|
||||
brand_map = {row[1]: row[0] for row in cursor.fetchall()}
|
||||
|
||||
for row in reader:
|
||||
brand_id = brand_map.get(row['brand_name'])
|
||||
if brand_id is None:
|
||||
print(f"Warning: Brand '{row['brand_name']}' not found in database")
|
||||
continue
|
||||
|
||||
cursor.execute(
|
||||
"""INSERT OR IGNORE INTO models
|
||||
(brand_id, name, body_type, generation, production_start_year, production_end_year)
|
||||
VALUES (?, ?, ?, ?, ?, ?)""",
|
||||
(
|
||||
brand_id,
|
||||
row['name'],
|
||||
row.get('body_type'),
|
||||
row.get('generation'),
|
||||
row.get('production_start_year'),
|
||||
row.get('production_end_year')
|
||||
)
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
print(f"Imported models from {csv_file}")
|
||||
|
||||
def create_sample_csv_files(self):
|
||||
"""Create sample CSV files with example data"""
|
||||
os.makedirs("data", exist_ok=True)
|
||||
|
||||
# Sample brands CSV
|
||||
with open("data/brands.csv", "w", newline="", encoding="utf-8") as csvfile:
|
||||
fieldnames = ["name", "country", "founded_year"]
|
||||
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
|
||||
writer.writeheader()
|
||||
writer.writerows([
|
||||
{"name": "Mercedes-Benz", "country": "Germany", "founded_year": 1926},
|
||||
{"name": "Audi", "country": "Germany", "founded_year": 1909},
|
||||
{"name": "Nissan", "country": "Japan", "founded_year": 1933},
|
||||
{"name": "Chevrolet", "country": "USA", "founded_year": 1911},
|
||||
{"name": "Volkswagen", "country": "Germany", "founded_year": 1937}
|
||||
])
|
||||
|
||||
# Sample engines CSV
|
||||
with open("data/engines.csv", "w", newline="", encoding="utf-8") as csvfile:
|
||||
fieldnames = ["name", "displacement_cc", "cylinders", "fuel_type", "power_hp", "torque_nm", "engine_code"]
|
||||
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
|
||||
writer.writeheader()
|
||||
writer.writerows([
|
||||
{"name": "VQ35DE", "displacement_cc": 3500, "cylinders": 6, "fuel_type": "gasoline", "power_hp": 280, "torque_nm": 260, "engine_code": "VQ35DE"},
|
||||
{"name": "LS3", "displacement_cc": 6200, "cylinders": 8, "fuel_type": "gasoline", "power_hp": 430, "torque_nm": 424, "engine_code": "LS3"},
|
||||
{"name": "EA888", "displacement_cc": 2000, "cylinders": 4, "fuel_type": "gasoline", "power_hp": 228, "torque_nm": 258, "engine_code": "EA888"},
|
||||
{"name": "M274", "displacement_cc": 2000, "cylinders": 4, "fuel_type": "gasoline", "power_hp": 241, "torque_nm": 273, "engine_code": "M274"}
|
||||
])
|
||||
|
||||
# Sample models CSV
|
||||
with open("data/models.csv", "w", newline="", encoding="utf-8") as csvfile:
|
||||
fieldnames = ["brand_name", "name", "body_type", "generation", "production_start_year", "production_end_year"]
|
||||
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
|
||||
writer.writeheader()
|
||||
writer.writerows([
|
||||
{"brand_name": "Toyota", "name": "Corolla", "body_type": "sedan", "generation": "E210", "production_start_year": 2018, "production_end_year": None},
|
||||
{"brand_name": "Honda", "name": "Accord", "body_type": "sedan", "generation": "X", "production_start_year": 2018, "production_end_year": None},
|
||||
{"brand_name": "Ford", "name": "F-150", "body_type": "truck", "generation": "13th Gen", "production_start_year": 2015, "production_end_year": None},
|
||||
{"brand_name": "BMW", "name": "3 Series", "body_type": "sedan", "generation": "G20", "production_start_year": 2018, "production_end_year": None}
|
||||
])
|
||||
|
||||
print("Sample CSV files created in data/ directory")
|
||||
|
||||
|
||||
def main():
|
||||
importer = CSVImporter()
|
||||
|
||||
# Create sample CSV files
|
||||
importer.create_sample_csv_files()
|
||||
|
||||
# Import sample data (these would be imported by the main script, but showing the functionality)
|
||||
print("CSV import functionality created. Sample CSV files are in the data/ directory.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
323
vehicle_database/scripts/database_manager.py
Normal file
323
vehicle_database/scripts/database_manager.py
Normal file
@@ -0,0 +1,323 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Vehicle Database Manager
|
||||
A script to initialize and manage the vehicle database with brands, years, models, and engines
|
||||
"""
|
||||
|
||||
import sqlite3
|
||||
import os
|
||||
from datetime import datetime
|
||||
from typing import List, Tuple
|
||||
|
||||
|
||||
class VehicleDatabaseManager:
|
||||
def __init__(self, db_path: str = "vehicle_database.db"):
|
||||
self.db_path = db_path
|
||||
self.connection = None
|
||||
|
||||
def connect(self):
|
||||
"""Connect to the SQLite database"""
|
||||
self.connection = sqlite3.connect(self.db_path)
|
||||
self.connection.row_factory = sqlite3.Row # Enable column access by name
|
||||
print(f"Connected to database: {self.db_path}")
|
||||
|
||||
def disconnect(self):
|
||||
"""Close the database connection"""
|
||||
if self.connection:
|
||||
self.connection.close()
|
||||
print("Disconnected from database")
|
||||
|
||||
def create_tables(self, schema_file: str = "sql/schema.sql"):
|
||||
"""Create tables from schema file"""
|
||||
if not os.path.exists(schema_file):
|
||||
raise FileNotFoundError(f"Schema file not found: {schema_file}")
|
||||
|
||||
with open(schema_file, 'r') as f:
|
||||
schema = f.read()
|
||||
|
||||
if self.connection:
|
||||
cursor = self.connection.cursor()
|
||||
cursor.executescript(schema)
|
||||
self.connection.commit()
|
||||
print("Tables created successfully")
|
||||
|
||||
def insert_brand(self, name: str, country: str = None, founded_year: int = None) -> int:
|
||||
"""Insert a new brand and return its ID"""
|
||||
cursor = self.connection.cursor()
|
||||
cursor.execute(
|
||||
"INSERT OR IGNORE INTO brands (name, country, founded_year) VALUES (?, ?, ?)",
|
||||
(name, country, founded_year)
|
||||
)
|
||||
self.connection.commit()
|
||||
# Return the ID of the inserted or existing brand
|
||||
cursor.execute("SELECT id FROM brands WHERE name = ?", (name,))
|
||||
return cursor.fetchone()[0]
|
||||
|
||||
def insert_engine(self, name: str, displacement_cc: float = None, cylinders: int = None,
|
||||
fuel_type: str = None, power_hp: int = None, torque_nm: int = None,
|
||||
engine_code: str = None) -> int:
|
||||
"""Insert a new engine and return its ID"""
|
||||
cursor = self.connection.cursor()
|
||||
cursor.execute(
|
||||
"""INSERT OR IGNORE INTO engines
|
||||
(name, displacement_cc, cylinders, fuel_type, power_hp, torque_nm, engine_code)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)""",
|
||||
(name, displacement_cc, cylinders, fuel_type, power_hp, torque_nm, engine_code)
|
||||
)
|
||||
self.connection.commit()
|
||||
# Return the ID of the inserted or existing engine
|
||||
cursor.execute("SELECT id FROM engines WHERE name = ?", (name,))
|
||||
return cursor.fetchone()[0]
|
||||
|
||||
def insert_model(self, brand_id: int, name: str, body_type: str = None,
|
||||
generation: str = None, production_start_year: int = None,
|
||||
production_end_year: int = None) -> int:
|
||||
"""Insert a new model and return its ID"""
|
||||
cursor = self.connection.cursor()
|
||||
cursor.execute(
|
||||
"""INSERT OR IGNORE INTO models
|
||||
(brand_id, name, body_type, generation, production_start_year, production_end_year)
|
||||
VALUES (?, ?, ?, ?, ?, ?)""",
|
||||
(brand_id, name, body_type, generation, production_start_year, production_end_year)
|
||||
)
|
||||
self.connection.commit()
|
||||
# Return the ID of the inserted or existing model
|
||||
cursor.execute("SELECT id FROM models WHERE brand_id = ? AND name = ?", (brand_id, name))
|
||||
return cursor.fetchone()[0]
|
||||
|
||||
def insert_year(self, year: int) -> int:
|
||||
"""Insert a new year and return its ID"""
|
||||
cursor = self.connection.cursor()
|
||||
cursor.execute("INSERT OR IGNORE INTO years (year) VALUES (?)", (year,))
|
||||
self.connection.commit()
|
||||
# Return the ID of the inserted or existing year
|
||||
cursor.execute("SELECT id FROM years WHERE year = ?", (year,))
|
||||
return cursor.fetchone()[0]
|
||||
|
||||
def insert_model_year_engine(self, model_id: int, year_id: int, engine_id: int,
|
||||
trim_level: str = None, drivetrain: str = None,
|
||||
transmission: str = None):
|
||||
"""Insert a model-year-engine combination"""
|
||||
cursor = self.connection.cursor()
|
||||
cursor.execute(
|
||||
"""INSERT OR REPLACE INTO model_year_engine
|
||||
(model_id, year_id, engine_id, trim_level, drivetrain, transmission)
|
||||
VALUES (?, ?, ?, ?, ?, ?)""",
|
||||
(model_id, year_id, engine_id, trim_level, drivetrain, transmission)
|
||||
)
|
||||
self.connection.commit()
|
||||
|
||||
def get_brands(self) -> List[Tuple]:
|
||||
"""Retrieve all brands"""
|
||||
cursor = self.connection.cursor()
|
||||
cursor.execute("SELECT * FROM brands ORDER BY name")
|
||||
return cursor.fetchall()
|
||||
|
||||
def get_models_by_brand(self, brand_id: int) -> List[Tuple]:
|
||||
"""Retrieve all models for a specific brand"""
|
||||
cursor = self.connection.cursor()
|
||||
cursor.execute("""
|
||||
SELECT m.*, b.name as brand_name
|
||||
FROM models m
|
||||
JOIN brands b ON m.brand_id = b.id
|
||||
WHERE m.brand_id = ?
|
||||
ORDER BY m.name
|
||||
""", (brand_id,))
|
||||
return cursor.fetchall()
|
||||
|
||||
def get_vehicle_info(self, brand_name: str = None, model_name: str = None,
|
||||
year: int = None, engine_name: str = None) -> List[Tuple]:
|
||||
"""Get comprehensive vehicle information based on filters"""
|
||||
query = """
|
||||
SELECT
|
||||
b.name AS brand,
|
||||
m.name AS model,
|
||||
y.year,
|
||||
e.name AS engine,
|
||||
e.displacement_cc,
|
||||
e.cylinders,
|
||||
e.fuel_type,
|
||||
e.power_hp,
|
||||
e.torque_nm,
|
||||
e.engine_code,
|
||||
mye.trim_level,
|
||||
mye.drivetrain,
|
||||
mye.transmission
|
||||
FROM model_year_engine mye
|
||||
JOIN models m ON mye.model_id = m.id
|
||||
JOIN brands b ON m.brand_id = b.id
|
||||
JOIN years y ON mye.year_id = y.id
|
||||
JOIN engines e ON mye.engine_id = e.id
|
||||
WHERE 1=1
|
||||
"""
|
||||
|
||||
params = []
|
||||
if brand_name:
|
||||
query += " AND b.name LIKE ?"
|
||||
params.append(f"%{brand_name}%")
|
||||
if model_name:
|
||||
query += " AND m.name LIKE ?"
|
||||
params.append(f"%{model_name}%")
|
||||
if year:
|
||||
query += " AND y.year = ?"
|
||||
params.append(year)
|
||||
if engine_name:
|
||||
query += " AND e.name LIKE ?"
|
||||
params.append(f"%{engine_name}%")
|
||||
|
||||
query += " ORDER BY b.name, m.name, y.year"
|
||||
|
||||
cursor = self.connection.cursor()
|
||||
cursor.execute(query, params)
|
||||
return cursor.fetchall()
|
||||
|
||||
|
||||
def populate_sample_data(db_manager: VehicleDatabaseManager):
|
||||
"""Populate the database with sample data"""
|
||||
print("Populating sample data...")
|
||||
|
||||
# Insert sample brands
|
||||
toyota_id = db_manager.insert_brand("Toyota", "Japan", 1937)
|
||||
honda_id = db_manager.insert_brand("Honda", "Japan", 1948)
|
||||
ford_id = db_manager.insert_brand("Ford", "USA", 1903)
|
||||
bmw_id = db_manager.insert_brand("BMW", "Germany", 1916)
|
||||
|
||||
# Insert sample engines
|
||||
engine_2jz = db_manager.insert_engine(
|
||||
"2JZ-GTE",
|
||||
displacement_cc=3000,
|
||||
cylinders=6,
|
||||
fuel_type="gasoline",
|
||||
power_hp=320,
|
||||
torque_nm=450,
|
||||
engine_code="2JZ-GTE"
|
||||
)
|
||||
|
||||
engine_k20 = db_manager.insert_engine(
|
||||
"K20C1",
|
||||
displacement_cc=2000,
|
||||
cylinders=4,
|
||||
fuel_type="gasoline",
|
||||
power_hp=280,
|
||||
torque_nm=260,
|
||||
engine_code="K20C1"
|
||||
)
|
||||
|
||||
engine_ecoboost = db_manager.insert_engine(
|
||||
"EcoBoost V6",
|
||||
displacement_cc=3500,
|
||||
cylinders=6,
|
||||
fuel_type="gasoline",
|
||||
power_hp=375,
|
||||
torque_nm=470,
|
||||
engine_code="EcoBoost V6"
|
||||
)
|
||||
|
||||
engine_n52 = db_manager.insert_engine(
|
||||
"N52B30",
|
||||
displacement_cc=3000,
|
||||
cylinders=6,
|
||||
fuel_type="gasoline",
|
||||
power_hp=255,
|
||||
torque_nm=310,
|
||||
engine_code="N52B30"
|
||||
)
|
||||
|
||||
# Insert sample models
|
||||
camry_id = db_manager.insert_model(
|
||||
toyota_id,
|
||||
"Camry",
|
||||
body_type="sedan",
|
||||
generation="XV70",
|
||||
production_start_year=2017,
|
||||
production_end_year=None
|
||||
)
|
||||
|
||||
civic_id = db_manager.insert_model(
|
||||
honda_id,
|
||||
"Civic",
|
||||
body_type="sedan",
|
||||
generation="XI",
|
||||
production_start_year=2016,
|
||||
production_end_year=None
|
||||
)
|
||||
|
||||
mustang_id = db_manager.insert_model(
|
||||
ford_id,
|
||||
"Mustang",
|
||||
body_type="coupe",
|
||||
generation="S550",
|
||||
production_start_year=2015,
|
||||
production_end_year=None
|
||||
)
|
||||
|
||||
x3_id = db_manager.insert_model(
|
||||
bmw_id,
|
||||
"X3",
|
||||
body_type="suv",
|
||||
generation="G01",
|
||||
production_start_year=2017,
|
||||
production_end_year=None
|
||||
)
|
||||
|
||||
# Insert years
|
||||
year_2020 = db_manager.insert_year(2020)
|
||||
year_2021 = db_manager.insert_year(2021)
|
||||
year_2022 = db_manager.insert_year(2022)
|
||||
|
||||
# Link models, years, and engines
|
||||
db_manager.insert_model_year_engine(civic_id, year_2020, engine_k20, "Sport", "FWD", "automatic")
|
||||
db_manager.insert_model_year_engine(mustang_id, year_2020, engine_ecoboost, "GT", "RWD", "automatic")
|
||||
db_manager.insert_model_year_engine(x3_id, year_2021, engine_n52, "xDrive30i", "AWD", "automatic")
|
||||
db_manager.insert_model_year_engine(camry_id, year_2022, engine_k20, "SE", "FWD", "automatic")
|
||||
|
||||
print("Sample data populated successfully!")
|
||||
|
||||
|
||||
def main():
|
||||
# Initialize the database manager
|
||||
db_manager = VehicleDatabaseManager()
|
||||
|
||||
try:
|
||||
# Connect to database
|
||||
db_manager.connect()
|
||||
|
||||
# Create tables
|
||||
db_manager.create_tables()
|
||||
|
||||
# Populate with sample data
|
||||
populate_sample_data(db_manager)
|
||||
|
||||
# Demonstrate queries
|
||||
print("\n--- All Brands ---")
|
||||
brands = db_manager.get_brands()
|
||||
for brand in brands:
|
||||
print(f"ID: {brand['id']}, Name: {brand['name']}, Country: {brand['country']}")
|
||||
|
||||
print(f"\n--- Models for Toyota (ID: {brands[0]['id']}) ---")
|
||||
toyota_models = db_manager.get_models_by_brand(brands[0]['id'])
|
||||
for model in toyota_models:
|
||||
print(f"Model: {model['name']}, Body Type: {model['body_type']}")
|
||||
|
||||
print("\n--- All Vehicle Information ---")
|
||||
all_vehicles = db_manager.get_vehicle_info()
|
||||
for vehicle in all_vehicles:
|
||||
print(f"{vehicle['brand']} {vehicle['model']} {vehicle['year']} - "
|
||||
f"{vehicle['engine']} ({vehicle['power_hp']} HP)")
|
||||
|
||||
print("\n--- Search for Honda Civic ---")
|
||||
honda_civic = db_manager.get_vehicle_info(brand_name="Honda", model_name="Civic")
|
||||
for vehicle in honda_civic:
|
||||
print(f"{vehicle['brand']} {vehicle['model']} {vehicle['year']} - "
|
||||
f"{vehicle['engine']} ({vehicle['power_hp']} HP)")
|
||||
|
||||
except Exception as e:
|
||||
print(f"An error occurred: {e}")
|
||||
|
||||
finally:
|
||||
# Close the connection
|
||||
db_manager.disconnect()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
193
vehicle_database/scripts/query_interface.py
Normal file
193
vehicle_database/scripts/query_interface.py
Normal file
@@ -0,0 +1,193 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Simple Query Interface for Vehicle Database
|
||||
Provides a command-line interface for searching the vehicle database
|
||||
"""
|
||||
|
||||
import sqlite3
|
||||
from typing import List, Tuple
|
||||
|
||||
|
||||
class VehicleQueryInterface:
|
||||
def __init__(self, db_path: str = "vehicle_database.db"):
|
||||
self.db_path = db_path
|
||||
|
||||
def search_vehicles(self, brand: str = None, model: str = None, year: int = None,
|
||||
engine: str = None, limit: int = 50) -> List[Tuple]:
|
||||
"""Search for vehicles based on various criteria"""
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
conn.row_factory = sqlite3.Row # Enable column access by name
|
||||
cursor = conn.cursor()
|
||||
|
||||
query = """
|
||||
SELECT
|
||||
b.name AS brand,
|
||||
m.name AS model,
|
||||
y.year,
|
||||
e.name AS engine,
|
||||
e.displacement_cc,
|
||||
e.cylinders,
|
||||
e.fuel_type,
|
||||
e.power_hp,
|
||||
mye.trim_level,
|
||||
mye.drivetrain,
|
||||
mye.transmission
|
||||
FROM model_year_engine mye
|
||||
JOIN models m ON mye.model_id = m.id
|
||||
JOIN brands b ON m.brand_id = b.id
|
||||
JOIN years y ON mye.year_id = y.id
|
||||
JOIN engines e ON mye.engine_id = e.id
|
||||
WHERE 1=1
|
||||
"""
|
||||
|
||||
params = []
|
||||
if brand:
|
||||
query += " AND b.name LIKE ?"
|
||||
params.append(f"%{brand}%")
|
||||
if model:
|
||||
query += " AND m.name LIKE ?"
|
||||
params.append(f"%{model}%")
|
||||
if year:
|
||||
query += " AND y.year = ?"
|
||||
params.append(year)
|
||||
if engine:
|
||||
query += " AND e.name LIKE ?"
|
||||
params.append(f"%{engine}%")
|
||||
|
||||
query += f" ORDER BY b.name, m.name, y.year LIMIT {limit}"
|
||||
|
||||
cursor.execute(query, params)
|
||||
results = cursor.fetchall()
|
||||
conn.close()
|
||||
|
||||
return results
|
||||
|
||||
def get_all_brands(self) -> List[Tuple]:
|
||||
"""Get a list of all brands in the database"""
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
conn.row_factory = sqlite3.Row
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute("SELECT DISTINCT name FROM brands ORDER BY name")
|
||||
results = cursor.fetchall()
|
||||
conn.close()
|
||||
|
||||
return [row[0] for row in results]
|
||||
|
||||
def get_models_by_brand(self, brand_name: str) -> List[Tuple]:
|
||||
"""Get all models for a specific brand"""
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
conn.row_factory = sqlite3.Row
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute("""
|
||||
SELECT DISTINCT m.name
|
||||
FROM models m
|
||||
JOIN brands b ON m.brand_id = b.id
|
||||
WHERE b.name = ?
|
||||
ORDER BY m.name
|
||||
""", (brand_name,))
|
||||
results = cursor.fetchall()
|
||||
conn.close()
|
||||
|
||||
return [row[0] for row in results]
|
||||
|
||||
def get_years_for_model(self, model_name: str) -> List[int]:
|
||||
"""Get all years for a specific model"""
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
conn.row_factory = sqlite3.Row
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute("""
|
||||
SELECT DISTINCT y.year
|
||||
FROM model_year_engine mye
|
||||
JOIN models m ON mye.model_id = m.id
|
||||
JOIN years y ON mye.year_id = y.id
|
||||
WHERE m.name = ?
|
||||
ORDER BY y.year
|
||||
""", (model_name,))
|
||||
results = cursor.fetchall()
|
||||
conn.close()
|
||||
|
||||
return [row[0] for row in results]
|
||||
|
||||
|
||||
def main():
|
||||
interface = VehicleQueryInterface()
|
||||
|
||||
print("Vehicle Database Query Interface")
|
||||
print("=================================")
|
||||
|
||||
while True:
|
||||
print("\nOptions:")
|
||||
print("1. Search vehicles")
|
||||
print("2. List all brands")
|
||||
print("3. List models for a brand")
|
||||
print("4. List years for a model")
|
||||
print("5. Exit")
|
||||
|
||||
choice = input("\nEnter your choice (1-5): ").strip()
|
||||
|
||||
if choice == "1":
|
||||
print("\nSearch for vehicles:")
|
||||
brand = input("Brand (optional): ").strip() or None
|
||||
model = input("Model (optional): ").strip() or None
|
||||
year_input = input("Year (optional): ").strip()
|
||||
year = int(year_input) if year_input else None
|
||||
engine = input("Engine (optional): ").strip() or None
|
||||
|
||||
results = interface.search_vehicles(brand=brand, model=model, year=year, engine=engine)
|
||||
|
||||
if results:
|
||||
print(f"\nFound {len(results)} result(s):")
|
||||
print("-" * 100)
|
||||
for i, vehicle in enumerate(results, 1):
|
||||
print(f"{i:2d}. {vehicle['year']} {vehicle['brand']} {vehicle['model']}")
|
||||
print(f" Engine: {vehicle['engine']} ({vehicle['power_hp']} HP, {vehicle['displacement_cc']} cc)")
|
||||
print(f" Trim: {vehicle['trim_level']}, Drivetrain: {vehicle['drivetrain']}, Transmission: {vehicle['transmission']}")
|
||||
print()
|
||||
else:
|
||||
print("No vehicles found matching your criteria.")
|
||||
|
||||
elif choice == "2":
|
||||
brands = interface.get_all_brands()
|
||||
print(f"\nAll brands ({len(brands)}):")
|
||||
for i, brand in enumerate(brands, 1):
|
||||
print(f"{i:2d}. {brand}")
|
||||
|
||||
elif choice == "3":
|
||||
brand = input("Enter brand name: ").strip()
|
||||
if brand:
|
||||
models = interface.get_models_by_brand(brand)
|
||||
if models:
|
||||
print(f"\nModels for {brand} ({len(models)}):")
|
||||
for i, model in enumerate(models, 1):
|
||||
print(f"{i:2d}. {model}")
|
||||
else:
|
||||
print(f"No models found for brand: {brand}")
|
||||
else:
|
||||
print("Please enter a brand name.")
|
||||
|
||||
elif choice == "4":
|
||||
model = input("Enter model name: ").strip()
|
||||
if model:
|
||||
years = interface.get_years_for_model(model)
|
||||
if years:
|
||||
print(f"\nYears for {model} ({len(years)}):")
|
||||
for i, year in enumerate(years, 1):
|
||||
print(f"{i:2d}. {year}")
|
||||
else:
|
||||
print(f"No years found for model: {model}")
|
||||
else:
|
||||
print("Please enter a model name.")
|
||||
|
||||
elif choice == "5":
|
||||
print("Thank you for using the Vehicle Database Query Interface!")
|
||||
break
|
||||
|
||||
else:
|
||||
print("Invalid choice. Please enter 1-5.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
0
vehicle_database/scripts/vehicle_database.db
Normal file
0
vehicle_database/scripts/vehicle_database.db
Normal file
29
vehicle_database/setup.sh
Executable file
29
vehicle_database/setup.sh
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
# Setup script for Vehicle Database
|
||||
|
||||
echo "Vehicle Database Setup"
|
||||
echo "======================"
|
||||
|
||||
# Check if Python3 is available
|
||||
if ! command -v python3 &> /dev/null; then
|
||||
echo "Python3 is required but not installed. Please install Python3 first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Python3 is available."
|
||||
|
||||
# Check if the database already exists
|
||||
if [ -f "vehicle_database.db" ]; then
|
||||
echo "Database already exists."
|
||||
else
|
||||
echo "Creating new database with sample data..."
|
||||
python3 scripts/database_manager.py
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Setup complete! Available scripts:"
|
||||
echo "1. Query Interface: python3 scripts/query_interface.py"
|
||||
echo "2. Database Manager: python3 scripts/database_manager.py"
|
||||
echo "3. CSV Importer: python3 scripts/csv_importer.py"
|
||||
echo ""
|
||||
echo "To start querying the database, run: python3 scripts/query_interface.py"
|
||||
66
vehicle_database/sql/schema.sql
Normal file
66
vehicle_database/sql/schema.sql
Normal file
@@ -0,0 +1,66 @@
|
||||
-- Vehicle Database Schema
|
||||
-- Tables for storing vehicle information: brands, years, models, and engines
|
||||
|
||||
-- Table for vehicle brands/manufacturers
|
||||
CREATE TABLE IF NOT EXISTS brands (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
country TEXT,
|
||||
founded_year INTEGER,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Table for engine specifications
|
||||
CREATE TABLE IF NOT EXISTS engines (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
displacement_cc REAL, -- Engine displacement in cubic centimeters
|
||||
cylinders INTEGER, -- Number of cylinders
|
||||
fuel_type TEXT CHECK(fuel_type IN ('gasoline', 'diesel', 'electric', 'hybrid', 'other')),
|
||||
power_hp INTEGER, -- Horsepower
|
||||
torque_nm INTEGER, -- Torque in Newton meters
|
||||
engine_code TEXT, -- Manufacturer engine code
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Table for vehicle models
|
||||
CREATE TABLE IF NOT EXISTS models (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
brand_id INTEGER NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
body_type TEXT CHECK(body_type IN ('sedan', 'hatchback', 'suv', 'truck', 'coupe', 'convertible', 'wagon', 'van', 'other')),
|
||||
generation TEXT, -- Model generation (e.g., MK1, MK2)
|
||||
production_start_year INTEGER,
|
||||
production_end_year INTEGER,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (brand_id) REFERENCES brands(id)
|
||||
);
|
||||
|
||||
-- Table for years (to link with models)
|
||||
CREATE TABLE IF NOT EXISTS years (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
year INTEGER NOT NULL UNIQUE,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Junction table to connect models, years, and engines
|
||||
CREATE TABLE IF NOT EXISTS model_year_engine (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
model_id INTEGER NOT NULL,
|
||||
year_id INTEGER NOT NULL,
|
||||
engine_id INTEGER NOT NULL,
|
||||
trim_level TEXT, -- Trim level (e.g., base, luxury, sport)
|
||||
drivetrain TEXT CHECK(drivetrain IN ('FWD', 'RWD', 'AWD', '4WD', 'other')),
|
||||
transmission TEXT CHECK(transmission IN ('manual', 'automatic', 'CVT', 'other')),
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (model_id) REFERENCES models(id),
|
||||
FOREIGN KEY (year_id) REFERENCES years(id),
|
||||
FOREIGN KEY (engine_id) REFERENCES engines(id),
|
||||
UNIQUE(model_id, year_id, engine_id, trim_level) -- Prevent duplicate combinations
|
||||
);
|
||||
|
||||
-- Indexes for better performance
|
||||
CREATE INDEX IF NOT EXISTS idx_models_brand ON models(brand_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_model_year_engine_model ON model_year_engine(model_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_model_year_engine_year ON model_year_engine(year_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_model_year_engine_engine ON model_year_engine(engine_id);
|
||||
BIN
vehicle_database/vehicle_database.db
Normal file
BIN
vehicle_database/vehicle_database.db
Normal file
Binary file not shown.
Reference in New Issue
Block a user