Initial Commit
This commit is contained in:
73
mvp-platform-services/vehicles/sql/schema/001_schema.sql
Normal file
73
mvp-platform-services/vehicles/sql/schema/001_schema.sql
Normal file
@@ -0,0 +1,73 @@
|
||||
-- Vehicles Platform Service Schema (baseline)
|
||||
CREATE SCHEMA IF NOT EXISTS vehicles;
|
||||
|
||||
-- Makes
|
||||
CREATE TABLE IF NOT EXISTS vehicles.make (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
name TEXT NOT NULL
|
||||
);
|
||||
|
||||
-- Models
|
||||
CREATE TABLE IF NOT EXISTS vehicles.model (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
make_id BIGINT NOT NULL REFERENCES vehicles.make(id) ON DELETE RESTRICT,
|
||||
name TEXT NOT NULL
|
||||
);
|
||||
|
||||
-- Model availability by year
|
||||
CREATE TABLE IF NOT EXISTS vehicles.model_year (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
model_id BIGINT NOT NULL REFERENCES vehicles.model(id) ON DELETE RESTRICT,
|
||||
year INTEGER NOT NULL CHECK (year BETWEEN 1950 AND 2100)
|
||||
);
|
||||
|
||||
-- Trims (year-specific)
|
||||
CREATE TABLE IF NOT EXISTS vehicles.trim (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
model_year_id BIGINT NOT NULL REFERENCES vehicles.model_year(id) ON DELETE RESTRICT,
|
||||
name TEXT NOT NULL
|
||||
);
|
||||
|
||||
-- Engines (canonical)
|
||||
CREATE TABLE IF NOT EXISTS vehicles.engine (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
code TEXT NULL,
|
||||
displacement_l NUMERIC(3,1) NULL,
|
||||
cylinders SMALLINT NULL,
|
||||
fuel_type TEXT NULL,
|
||||
aspiration TEXT NULL
|
||||
);
|
||||
|
||||
-- Trim to Engine mapping (many-to-many)
|
||||
CREATE TABLE IF NOT EXISTS vehicles.trim_engine (
|
||||
trim_id BIGINT NOT NULL REFERENCES vehicles.trim(id) ON DELETE RESTRICT,
|
||||
engine_id BIGINT NOT NULL REFERENCES vehicles.engine(id) ON DELETE RESTRICT,
|
||||
PRIMARY KEY (trim_id, engine_id)
|
||||
);
|
||||
|
||||
-- Optional: Transmissions (reserved for future)
|
||||
CREATE TABLE IF NOT EXISTS vehicles.transmission (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
type TEXT NULL,
|
||||
gears SMALLINT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS vehicles.trim_transmission (
|
||||
trim_id BIGINT NOT NULL REFERENCES vehicles.trim(id) ON DELETE RESTRICT,
|
||||
transmission_id BIGINT NOT NULL REFERENCES vehicles.transmission(id) ON DELETE RESTRICT,
|
||||
PRIMARY KEY (trim_id, transmission_id)
|
||||
);
|
||||
|
||||
-- Optional: Performance (reserved for future)
|
||||
CREATE TABLE IF NOT EXISTS vehicles.performance (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
engine_id BIGINT NULL REFERENCES vehicles.engine(id) ON DELETE SET NULL,
|
||||
trim_id BIGINT NULL REFERENCES vehicles.trim(id) ON DELETE SET NULL,
|
||||
horsepower NUMERIC(6,2) NULL,
|
||||
torque NUMERIC(6,2) NULL,
|
||||
top_speed NUMERIC(6,2) NULL,
|
||||
zero_to_sixty NUMERIC(4,2) NULL
|
||||
);
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
-- Uniques and indexes to enforce data integrity and performance
|
||||
|
||||
-- Unique, case-insensitive names
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS ux_make_name ON vehicles.make (lower(name));
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS ux_model_make_name ON vehicles.model (make_id, lower(name));
|
||||
|
||||
-- Model/Year availability
|
||||
ALTER TABLE vehicles.model_year
|
||||
ADD CONSTRAINT ux_model_year UNIQUE (model_id, year);
|
||||
CREATE INDEX IF NOT EXISTS ix_model_year_year_model ON vehicles.model_year (year, model_id);
|
||||
|
||||
-- Trims are unique per model_year by name (case-insensitive)
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS ux_trim_modelyear_name ON vehicles.trim (model_year_id, lower(name));
|
||||
CREATE INDEX IF NOT EXISTS ix_trim_modelyear_name ON vehicles.trim (model_year_id, name);
|
||||
|
||||
-- Engine uniqueness (prefer code when present)
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS ux_engine_code_not_null ON vehicles.engine (code) WHERE code IS NOT NULL;
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS ux_engine_name ON vehicles.engine (lower(name));
|
||||
|
||||
-- Bridge indexes
|
||||
CREATE INDEX IF NOT EXISTS ix_trim_engine_trim ON vehicles.trim_engine (trim_id);
|
||||
CREATE INDEX IF NOT EXISTS ix_trim_engine_engine ON vehicles.trim_engine (engine_id);
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
-- Minimal seed data for testing dropdown hierarchy
|
||||
INSERT INTO vehicles.make (name) VALUES ('Honda') ON CONFLICT DO NOTHING;
|
||||
INSERT INTO vehicles.make (name) VALUES ('Toyota') ON CONFLICT DO NOTHING;
|
||||
|
||||
-- Resolve make ids
|
||||
WITH m AS (
|
||||
SELECT id FROM vehicles.make WHERE lower(name) = lower('Honda')
|
||||
)
|
||||
INSERT INTO vehicles.model (make_id, name)
|
||||
SELECT m.id, 'Civic' FROM m
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
WITH m AS (
|
||||
SELECT id FROM vehicles.make WHERE lower(name) = lower('Toyota')
|
||||
)
|
||||
INSERT INTO vehicles.model (make_id, name)
|
||||
SELECT m.id, 'Corolla' FROM m
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- Model years
|
||||
WITH mo AS (
|
||||
SELECT id FROM vehicles.model WHERE lower(name) = lower('Civic')
|
||||
)
|
||||
INSERT INTO vehicles.model_year (model_id, year)
|
||||
SELECT mo.id, 2024 FROM mo ON CONFLICT DO NOTHING;
|
||||
|
||||
WITH mo AS (
|
||||
SELECT id FROM vehicles.model WHERE lower(name) = lower('Corolla')
|
||||
)
|
||||
INSERT INTO vehicles.model_year (model_id, year)
|
||||
SELECT mo.id, 2024 FROM mo ON CONFLICT DO NOTHING;
|
||||
|
||||
-- Trims
|
||||
WITH my AS (
|
||||
SELECT my.id FROM vehicles.model_year my
|
||||
JOIN vehicles.model mo ON mo.id = my.model_id
|
||||
WHERE lower(mo.name) = lower('Civic') AND my.year = 2024
|
||||
)
|
||||
INSERT INTO vehicles.trim (model_year_id, name)
|
||||
SELECT my.id, 'LX' FROM my ON CONFLICT DO NOTHING;
|
||||
|
||||
WITH my AS (
|
||||
SELECT my.id FROM vehicles.model_year my
|
||||
JOIN vehicles.model mo ON mo.id = my.model_id
|
||||
WHERE lower(mo.name) = lower('Corolla') AND my.year = 2024
|
||||
)
|
||||
INSERT INTO vehicles.trim (model_year_id, name)
|
||||
SELECT my.id, 'LE' FROM my ON CONFLICT DO NOTHING;
|
||||
|
||||
-- Engines
|
||||
INSERT INTO vehicles.engine (name, code, displacement_l, cylinders, fuel_type, aspiration)
|
||||
VALUES ('2.0L I4', 'K20', 2.0, 4, 'Gasoline', 'NA')
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
INSERT INTO vehicles.engine (name, code, displacement_l, cylinders, fuel_type, aspiration)
|
||||
VALUES ('2.0L I4', 'M20', 2.0, 4, 'Gasoline', 'NA')
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- Map engines to trims
|
||||
WITH t AS (
|
||||
SELECT t.id AS trim_id, e.id AS engine_id
|
||||
FROM vehicles.trim t
|
||||
JOIN vehicles.model_year my ON my.id = t.model_year_id AND my.year = 2024
|
||||
JOIN vehicles.model mo ON mo.id = my.model_id
|
||||
JOIN vehicles.make ma ON ma.id = mo.make_id
|
||||
JOIN vehicles.engine e ON e.code IN ('K20','M20')
|
||||
WHERE lower(ma.name) = lower('Honda') AND lower(mo.name) = lower('Civic') AND lower(t.name) = lower('LX')
|
||||
)
|
||||
INSERT INTO vehicles.trim_engine (trim_id, engine_id)
|
||||
SELECT trim_id, engine_id FROM t ON CONFLICT DO NOTHING;
|
||||
@@ -0,0 +1,105 @@
|
||||
-- Seed sample data based on ETL source filter (etl/sources/makes.json)
|
||||
-- Focus on Chevrolet (Corvette) and GMC (Sierra 1500)
|
||||
|
||||
-- Makes
|
||||
INSERT INTO vehicles.make (name) VALUES ('Chevrolet') ON CONFLICT DO NOTHING;
|
||||
INSERT INTO vehicles.make (name) VALUES ('GMC') ON CONFLICT DO NOTHING;
|
||||
|
||||
-- Chevrolet Corvette
|
||||
WITH chevy AS (
|
||||
SELECT id FROM vehicles.make WHERE lower(name) = lower('Chevrolet')
|
||||
)
|
||||
INSERT INTO vehicles.model (make_id, name)
|
||||
SELECT chevy.id, 'Corvette' FROM chevy
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
WITH corvette AS (
|
||||
SELECT id FROM vehicles.model WHERE lower(name) = lower('Corvette')
|
||||
)
|
||||
INSERT INTO vehicles.model_year (model_id, year)
|
||||
SELECT corvette.id, 2024 FROM corvette
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- Corvette trims (2024)
|
||||
WITH my AS (
|
||||
SELECT my.id
|
||||
FROM vehicles.model_year my
|
||||
JOIN vehicles.model mo ON mo.id = my.model_id
|
||||
WHERE lower(mo.name) = lower('Corvette') AND my.year = 2024
|
||||
)
|
||||
INSERT INTO vehicles.trim (model_year_id, name)
|
||||
SELECT my.id, t.name
|
||||
FROM my, (VALUES ('Stingray'), ('Z06')) AS t(name)
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- Corvette engines
|
||||
INSERT INTO vehicles.engine (name, code, displacement_l, cylinders, fuel_type, aspiration)
|
||||
VALUES
|
||||
('6.2L V8 LT2', 'LT2', 6.2, 8, 'Gasoline', 'NA'),
|
||||
('5.5L V8 LT6', 'LT6', 5.5, 8, 'Gasoline', 'NA')
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- Map Corvette engines to trims
|
||||
WITH t AS (
|
||||
SELECT t.id AS trim_id, t.name AS trim_name
|
||||
FROM vehicles.trim t
|
||||
JOIN vehicles.model_year my ON my.id = t.model_year_id AND my.year = 2024
|
||||
JOIN vehicles.model mo ON mo.id = my.model_id AND lower(mo.name) = lower('Corvette')
|
||||
)
|
||||
INSERT INTO vehicles.trim_engine (trim_id, engine_id)
|
||||
SELECT t.trim_id, e.id
|
||||
FROM t
|
||||
JOIN vehicles.engine e
|
||||
ON (t.trim_name = 'Stingray' AND e.code = 'LT2')
|
||||
OR (t.trim_name = 'Z06' AND e.code = 'LT6')
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- GMC Sierra 1500
|
||||
WITH gmc AS (
|
||||
SELECT id FROM vehicles.make WHERE lower(name) = lower('GMC')
|
||||
)
|
||||
INSERT INTO vehicles.model (make_id, name)
|
||||
SELECT gmc.id, 'Sierra 1500' FROM gmc
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
WITH sierra AS (
|
||||
SELECT id FROM vehicles.model WHERE lower(name) = lower('Sierra 1500')
|
||||
)
|
||||
INSERT INTO vehicles.model_year (model_id, year)
|
||||
SELECT sierra.id, 2024 FROM sierra
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- Sierra trims (2024)
|
||||
WITH my AS (
|
||||
SELECT my.id
|
||||
FROM vehicles.model_year my
|
||||
JOIN vehicles.model mo ON mo.id = my.model_id
|
||||
WHERE lower(mo.name) = lower('Sierra 1500') AND my.year = 2024
|
||||
)
|
||||
INSERT INTO vehicles.trim (model_year_id, name)
|
||||
SELECT my.id, t.name
|
||||
FROM my, (VALUES ('SLE'), ('Denali')) AS t(name)
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- Sierra engines
|
||||
INSERT INTO vehicles.engine (name, code, displacement_l, cylinders, fuel_type, aspiration)
|
||||
VALUES
|
||||
('5.3L V8 L84', 'L84', 5.3, 8, 'Gasoline', 'NA'),
|
||||
('6.2L V8 L87', 'L87', 6.2, 8, 'Gasoline', 'NA')
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- Map Sierra engines to trims
|
||||
WITH t AS (
|
||||
SELECT t.id AS trim_id, t.name AS trim_name
|
||||
FROM vehicles.trim t
|
||||
JOIN vehicles.model_year my ON my.id = t.model_year_id AND my.year = 2024
|
||||
JOIN vehicles.model mo ON mo.id = my.model_id AND lower(mo.name) = lower('Sierra 1500')
|
||||
)
|
||||
INSERT INTO vehicles.trim_engine (trim_id, engine_id)
|
||||
SELECT t.trim_id, e.id
|
||||
FROM t
|
||||
JOIN vehicles.engine e
|
||||
ON (t.trim_name = 'SLE' AND e.code = 'L84')
|
||||
OR (t.trim_name = 'Denali' AND e.code = 'L87')
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
-- Seed specific vehicle combinations requested
|
||||
|
||||
-- Ensure makes exist
|
||||
INSERT INTO vehicles.make (name) VALUES ('GMC') ON CONFLICT DO NOTHING;
|
||||
INSERT INTO vehicles.make (name) VALUES ('Chevrolet') ON CONFLICT DO NOTHING;
|
||||
|
||||
-- Ensure models exist under their makes
|
||||
WITH m AS (
|
||||
SELECT id FROM vehicles.make WHERE lower(name) = lower('GMC')
|
||||
)
|
||||
INSERT INTO vehicles.model (make_id, name)
|
||||
SELECT m.id, 'Sierra 1500' FROM m
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
WITH m AS (
|
||||
SELECT id FROM vehicles.make WHERE lower(name) = lower('Chevrolet')
|
||||
)
|
||||
INSERT INTO vehicles.model (make_id, name)
|
||||
SELECT m.id, 'Corvette' FROM m
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- Model years
|
||||
WITH mo AS (
|
||||
SELECT id FROM vehicles.model WHERE lower(name) = lower('Sierra 1500')
|
||||
)
|
||||
INSERT INTO vehicles.model_year (model_id, year)
|
||||
SELECT mo.id, 2023 FROM mo ON CONFLICT DO NOTHING;
|
||||
|
||||
WITH mo AS (
|
||||
SELECT id FROM vehicles.model WHERE lower(name) = lower('Corvette')
|
||||
)
|
||||
INSERT INTO vehicles.model_year (model_id, year)
|
||||
SELECT mo.id, 2017 FROM mo ON CONFLICT DO NOTHING;
|
||||
|
||||
-- Trims
|
||||
WITH my AS (
|
||||
SELECT my.id FROM vehicles.model_year my
|
||||
JOIN vehicles.model mo ON mo.id = my.model_id
|
||||
WHERE lower(mo.name) = lower('Sierra 1500') AND my.year = 2023
|
||||
)
|
||||
INSERT INTO vehicles.trim (model_year_id, name)
|
||||
SELECT my.id, 'AT4x' FROM my ON CONFLICT DO NOTHING;
|
||||
|
||||
WITH my AS (
|
||||
SELECT my.id FROM vehicles.model_year my
|
||||
JOIN vehicles.model mo ON mo.id = my.model_id
|
||||
WHERE lower(mo.name) = lower('Corvette') AND my.year = 2017
|
||||
)
|
||||
INSERT INTO vehicles.trim (model_year_id, name)
|
||||
SELECT my.id, 'Z06 Convertible' FROM my ON CONFLICT DO NOTHING;
|
||||
|
||||
-- Engines (ensure canonical engines exist)
|
||||
INSERT INTO vehicles.engine (name, code, displacement_l, cylinders, fuel_type, aspiration)
|
||||
VALUES ('6.2L V8 L87', 'L87', 6.2, 8, 'Gasoline', 'NA')
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
INSERT INTO vehicles.engine (name, code, displacement_l, cylinders, fuel_type, aspiration)
|
||||
VALUES ('6.2L V8 LT4', 'LT4', 6.2, 8, 'Gasoline', 'SC')
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- Map engines to trims
|
||||
WITH t AS (
|
||||
SELECT t.id AS trim_id, t.name AS trim_name, my.year, mo.name AS model_name
|
||||
FROM vehicles.trim t
|
||||
JOIN vehicles.model_year my ON my.id = t.model_year_id
|
||||
JOIN vehicles.model mo ON mo.id = my.model_id
|
||||
)
|
||||
INSERT INTO vehicles.trim_engine (trim_id, engine_id)
|
||||
SELECT t.trim_id, e.id
|
||||
FROM t
|
||||
JOIN vehicles.engine e
|
||||
ON (t.model_name = 'Sierra 1500' AND t.year = 2023 AND t.trim_name = 'AT4x' AND e.code = 'L87')
|
||||
OR (t.model_name = 'Corvette' AND t.year = 2017 AND t.trim_name = 'Z06 Convertible' AND e.code = 'LT4')
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
Reference in New Issue
Block a user