CREATE EXTENSION IF NOT EXISTS pg_trgm WITH SCHEMA public; --> statement-breakpoint CREATE SCHEMA "cars"; --> statement-breakpoint CREATE TABLE "cars"."brands" ( "id" serial PRIMARY KEY, "slug" text NOT NULL, "name" text NOT NULL, "country" text, "model_count" integer DEFAULT 0 NOT NULL, "nl_count" integer DEFAULT 0 NOT NULL, "first_year" smallint, "last_year" smallint, "sources" text[] DEFAULT '{}'::text[] NOT NULL, "created_at" timestamp with time zone DEFAULT now() NOT NULL, "updated_at" timestamp with time zone DEFAULT now() NOT NULL ); --> statement-breakpoint CREATE TABLE "cars"."models" ( "id" serial PRIMARY KEY, "dex" integer NOT NULL, "brand_id" integer NOT NULL, "slug" text NOT NULL, "name" text NOT NULL, "search" text NOT NULL, "first_year" smallint, "last_year" smallint, "bodies" text[] DEFAULT '{}'::text[] NOT NULL, "size_classes" text[] DEFAULT '{}'::text[] NOT NULL, "fuels" text[] DEFAULT '{}'::text[] NOT NULL, "drives" text[] DEFAULT '{}'::text[] NOT NULL, "transmissions" text[] DEFAULT '{}'::text[] NOT NULL, "engine_l_min" real, "engine_l_max" real, "cylinders_min" smallint, "cylinders_max" smallint, "turbo" boolean, "power_kw_min" real, "power_kw_max" real, "l100_min" real, "l100_max" real, "co2_min" smallint, "co2_max" smallint, "mpg_min" real, "mpg_max" real, "range_km_max" smallint, "seats" smallint, "doors" smallint, "mass_kg" smallint, "nl_count" integer DEFAULT 0 NOT NULL, "nl_rank" integer, "nl_first_year" smallint, "nl_last_year" smallint, "nl_price" integer, "nl_price_latest" integer, "nl_price_latest_year" smallint, "nl_years" jsonb DEFAULT '[]' NOT NULL, "nl_names" jsonb DEFAULT '[]' NOT NULL, "us_years" smallint[] DEFAULT '{}'::smallint[] NOT NULL, "variant_count" integer DEFAULT 0 NOT NULL, "sources" text[] DEFAULT '{}'::text[] NOT NULL, "created_at" timestamp with time zone DEFAULT now() NOT NULL, "updated_at" timestamp with time zone DEFAULT now() NOT NULL ); --> statement-breakpoint CREATE TABLE "cars"."variants" ( "id" serial PRIMARY KEY, "model_id" integer NOT NULL, "source" text DEFAULT 'fueleconomy.gov' NOT NULL, "source_id" integer, "year" smallint NOT NULL, "name" text NOT NULL, "engine_l" real, "cylinders" smallint, "transmission" text, "drive" text, "fuel" text, "size_class" text, "mpg_city" real, "mpg_hwy" real, "mpg_comb" real, "co2_gpm" smallint, "range_mi" smallint, "ev_motor" text, "turbo" boolean DEFAULT false NOT NULL, "supercharged" boolean DEFAULT false NOT NULL ); --> statement-breakpoint CREATE UNIQUE INDEX "brands_slug_key" ON "cars"."brands" ("slug");--> statement-breakpoint CREATE UNIQUE INDEX "models_dex_key" ON "cars"."models" ("dex");--> statement-breakpoint CREATE UNIQUE INDEX "models_brand_slug_key" ON "cars"."models" ("brand_id","slug");--> statement-breakpoint CREATE INDEX "models_nl_count_idx" ON "cars"."models" ("nl_count");--> statement-breakpoint CREATE INDEX "models_search_trgm_idx" ON "cars"."models" USING gin ("search" public.gin_trgm_ops);--> statement-breakpoint CREATE INDEX "variants_model_year_idx" ON "cars"."variants" ("model_id","year");--> statement-breakpoint ALTER TABLE "cars"."models" ADD CONSTRAINT "models_brand_id_brands_id_fkey" FOREIGN KEY ("brand_id") REFERENCES "cars"."brands"("id") ON DELETE CASCADE;--> statement-breakpoint ALTER TABLE "cars"."variants" ADD CONSTRAINT "variants_model_id_models_id_fkey" FOREIGN KEY ("model_id") REFERENCES "cars"."models"("id") ON DELETE CASCADE; --> statement-breakpoint -- Hand-written: updated_at triggers, grants, GUI registration. Data comes from scripts/cars-import.ts. DO $$ DECLARE t text; BEGIN FOREACH t IN ARRAY ARRAY['brands','models'] LOOP EXECUTE format('CREATE TRIGGER touch_updated_at BEFORE UPDATE ON cars.%I FOR EACH ROW EXECUTE FUNCTION meta.touch_updated_at()', t); END LOOP; END $$; --> statement-breakpoint DO $$ BEGIN IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'personal_app') THEN GRANT USAGE ON SCHEMA cars TO personal_app; GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA cars TO personal_app; GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA cars TO personal_app; ALTER DEFAULT PRIVILEGES IN SCHEMA cars GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO personal_app; ALTER DEFAULT PRIVILEGES IN SCHEMA cars GRANT USAGE, SELECT ON SEQUENCES TO personal_app; END IF; IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'personal_ro') THEN GRANT USAGE ON SCHEMA cars TO personal_ro; GRANT SELECT ON ALL TABLES IN SCHEMA cars TO personal_ro; ALTER DEFAULT PRIVILEGES IN SCHEMA cars GRANT SELECT ON TABLES TO personal_ro; END IF; END $$; --> statement-breakpoint DO $$ BEGIN IF to_regclass('meta.tables') IS NOT NULL THEN INSERT INTO meta.tables (schema_name, table_name, slug, display_name, kind, editable, has_done, sort_order) VALUES ('cars','brands','cars-brands','Car brands','core',false,false,1000), ('cars','models','cars-models','Car models','core',false,false,1000) ON CONFLICT DO NOTHING; IF has_function_privilege('meta.sync(integer)', 'EXECUTE') THEN PERFORM meta.sync(); END IF; END IF; END $$;