Make/Model Data Loading

This commit is contained in:
Eric Gullickson
2025-11-07 13:51:47 -06:00
parent 060867e796
commit daf1f71e2c
11 changed files with 817 additions and 97 deletions

View File

@@ -0,0 +1,139 @@
-- Create dedicated schema for normalized vehicle lookup data
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM pg_namespace WHERE nspname = 'vehicles'
) THEN
EXECUTE 'CREATE SCHEMA vehicles';
END IF;
END;
$$;
-- Create manufacturers table
CREATE TABLE IF NOT EXISTS vehicles.make (
id BIGSERIAL PRIMARY KEY,
name VARCHAR(150) NOT NULL UNIQUE,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE OR REPLACE FUNCTION vehicles.touch_updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
DROP TRIGGER IF EXISTS touch_make_updated_at ON vehicles.make;
CREATE TRIGGER touch_make_updated_at
BEFORE UPDATE ON vehicles.make
FOR EACH ROW
EXECUTE FUNCTION vehicles.touch_updated_at();
-- Create models table
CREATE TABLE IF NOT EXISTS vehicles.model (
id BIGSERIAL PRIMARY KEY,
make_id BIGINT NOT NULL REFERENCES vehicles.make(id) ON DELETE CASCADE,
name VARCHAR(150) NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT vehicles_model_unique UNIQUE(make_id, name)
);
DROP TRIGGER IF EXISTS touch_model_updated_at ON vehicles.model;
CREATE TRIGGER touch_model_updated_at
BEFORE UPDATE ON vehicles.model
FOR EACH ROW
EXECUTE FUNCTION vehicles.touch_updated_at();
-- Create model_year table
CREATE TABLE IF NOT EXISTS vehicles.model_year (
id BIGSERIAL PRIMARY KEY,
model_id BIGINT NOT NULL REFERENCES vehicles.model(id) ON DELETE CASCADE,
year INTEGER NOT NULL CHECK (year BETWEEN 1900 AND 2100),
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT vehicles_model_year_unique UNIQUE(model_id, year)
);
CREATE INDEX IF NOT EXISTS idx_model_year_year ON vehicles.model_year(year DESC);
DROP TRIGGER IF EXISTS touch_model_year_updated_at ON vehicles.model_year;
CREATE TRIGGER touch_model_year_updated_at
BEFORE UPDATE ON vehicles.model_year
FOR EACH ROW
EXECUTE FUNCTION vehicles.touch_updated_at();
-- Create trims table
CREATE TABLE IF NOT EXISTS vehicles.trim (
id BIGSERIAL PRIMARY KEY,
model_year_id BIGINT NOT NULL REFERENCES vehicles.model_year(id) ON DELETE CASCADE,
name VARCHAR(150) NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT vehicles_trim_unique UNIQUE(model_year_id, name)
);
CREATE INDEX IF NOT EXISTS idx_trim_model_year ON vehicles.trim(model_year_id);
DROP TRIGGER IF EXISTS touch_trim_updated_at ON vehicles.trim;
CREATE TRIGGER touch_trim_updated_at
BEFORE UPDATE ON vehicles.trim
FOR EACH ROW
EXECUTE FUNCTION vehicles.touch_updated_at();
-- Create engines table
CREATE TABLE IF NOT EXISTS vehicles.engine (
id BIGSERIAL PRIMARY KEY,
name VARCHAR(200) NOT NULL UNIQUE,
code VARCHAR(50),
displacement_l NUMERIC(5,2),
cylinders SMALLINT,
fuel_type VARCHAR(50),
aspiration VARCHAR(50),
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);
DROP TRIGGER IF EXISTS touch_engine_updated_at ON vehicles.engine;
CREATE TRIGGER touch_engine_updated_at
BEFORE UPDATE ON vehicles.engine
FOR EACH ROW
EXECUTE FUNCTION vehicles.touch_updated_at();
-- Create trim-engine bridge table
CREATE TABLE IF NOT EXISTS vehicles.trim_engine (
trim_id BIGINT NOT NULL REFERENCES vehicles.trim(id) ON DELETE CASCADE,
engine_id BIGINT NOT NULL REFERENCES vehicles.engine(id) ON DELETE CASCADE,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (trim_id, engine_id)
);
-- Create transmissions table (static manual/automatic for now)
CREATE TABLE IF NOT EXISTS vehicles.transmission (
id BIGSERIAL PRIMARY KEY,
name VARCHAR(50) NOT NULL UNIQUE,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);
DROP TRIGGER IF EXISTS touch_transmission_updated_at ON vehicles.transmission;
CREATE TRIGGER touch_transmission_updated_at
BEFORE UPDATE ON vehicles.transmission
FOR EACH ROW
EXECUTE FUNCTION vehicles.touch_updated_at();
-- Optional bridge for future proofing (not yet populated)
CREATE TABLE IF NOT EXISTS vehicles.trim_transmission (
trim_id BIGINT NOT NULL REFERENCES vehicles.trim(id) ON DELETE CASCADE,
transmission_id BIGINT NOT NULL REFERENCES vehicles.transmission(id) ON DELETE CASCADE,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (trim_id, transmission_id)
);
-- Helpful indexes for cascading dropdown lookups
CREATE INDEX IF NOT EXISTS idx_model_make ON vehicles.model(make_id);
CREATE INDEX IF NOT EXISTS idx_trim_name ON vehicles.trim(LOWER(name));
CREATE INDEX IF NOT EXISTS idx_engine_name ON vehicles.engine(LOWER(name));
CREATE INDEX IF NOT EXISTS idx_trim_engine_engine ON vehicles.trim_engine(engine_id);