Fast IAAI implementation
This commit is contained in:
165
alembic/versions/0001_ensure_sync_schema.py
Normal file
165
alembic/versions/0001_ensure_sync_schema.py
Normal file
@@ -0,0 +1,165 @@
|
||||
"""bootstrap standalone iaai schema
|
||||
|
||||
Revision ID: 0001_ensure_sync_schema
|
||||
Revises:
|
||||
Create Date: 2026-04-08 00:00:00
|
||||
"""
|
||||
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "0001_ensure_sync_schema"
|
||||
down_revision: Union[str, Sequence[str], None] = None
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def _create_enum_if_missing(type_name: str, values: tuple[str, ...]) -> None:
|
||||
values_sql = ", ".join("'" + value.replace("'", "''") + "'" for value in values)
|
||||
op.execute(
|
||||
f"""
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM pg_type t
|
||||
JOIN pg_namespace n ON n.oid = t.typnamespace
|
||||
WHERE t.typname = '{type_name}'
|
||||
AND n.nspname = 'public'
|
||||
) THEN
|
||||
CREATE TYPE public.{type_name} AS ENUM ({values_sql});
|
||||
END IF;
|
||||
END
|
||||
$$;
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
_create_enum_if_missing("currencyenum", ("JPY", "USD", "EUR", "RUB", "KRW", "AED", "GBP", "CAD"))
|
||||
_create_enum_if_missing("driveenum", ("FWD", "RWD", "TWO_WD", "FOUR_WD", "2WD", "4WD", "NA"))
|
||||
_create_enum_if_missing("gearboxenum", ("AT", "CVT", "MT", "EV", "NA"))
|
||||
_create_enum_if_missing("steeringwheelenum", ("LEFT", "RIGHT", "left", "right", "NA"))
|
||||
_create_enum_if_missing(
|
||||
"bodytypeenum",
|
||||
(
|
||||
"COUPE",
|
||||
"SUV",
|
||||
"HATCHBACK",
|
||||
"MINIVAN",
|
||||
"SEDAN",
|
||||
"NA",
|
||||
"Station Wagon",
|
||||
"Pickup",
|
||||
"Truck",
|
||||
"Open",
|
||||
"RV",
|
||||
"Other",
|
||||
"STATION_WAGON",
|
||||
"PICKUP",
|
||||
"TRUCK",
|
||||
"OPEN",
|
||||
"OTHER",
|
||||
),
|
||||
)
|
||||
_create_enum_if_missing("countryenum", ("JP", "KR", "US", "CA", "NA"))
|
||||
_create_enum_if_missing(
|
||||
"originenum",
|
||||
(
|
||||
"TAU",
|
||||
"CARSENSOR",
|
||||
"HANAMARU",
|
||||
"ENCAR",
|
||||
"KURUMA_TRADER",
|
||||
"carsensor",
|
||||
"encar",
|
||||
"kuruma_trader",
|
||||
"asnet",
|
||||
"kababa",
|
||||
"ACV",
|
||||
"COPART",
|
||||
"copart",
|
||||
"NA",
|
||||
"ASNET",
|
||||
"KABABA",
|
||||
),
|
||||
)
|
||||
_create_enum_if_missing("sellingtypeenum", ("STOCK", "AUCTION", "TENDER", "stock", "auction", "tender", "NA"))
|
||||
|
||||
op.execute(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS public.cars (
|
||||
id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
parser_id VARCHAR(50) NOT NULL UNIQUE,
|
||||
brand VARCHAR(50) NOT NULL,
|
||||
model VARCHAR(50) NOT NULL,
|
||||
year INTEGER NULL,
|
||||
price BIGINT NULL,
|
||||
currency public.currencyenum NOT NULL DEFAULT 'USD',
|
||||
mileage INTEGER NOT NULL DEFAULT 0,
|
||||
country public.countryenum NOT NULL DEFAULT 'NA',
|
||||
is_sold BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
color VARCHAR NOT NULL DEFAULT 'other',
|
||||
drive public.driveenum NULL,
|
||||
gearbox public.gearboxenum NULL,
|
||||
steering_wheel public.steeringwheelenum NULL,
|
||||
body_type public.bodytypeenum NOT NULL DEFAULT 'OTHER',
|
||||
engine_volume INTEGER NULL,
|
||||
selling_type public.sellingtypeenum NOT NULL DEFAULT 'NA',
|
||||
one_owner BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
new_car BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
is_hidden BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
origin public.originenum NOT NULL DEFAULT 'NA',
|
||||
origin_url VARCHAR NOT NULL,
|
||||
origin_id VARCHAR NOT NULL UNIQUE,
|
||||
is_damaged BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
evaluation VARCHAR NULL,
|
||||
non_smoking BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
rental BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
repair_history BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
slug VARCHAR NOT NULL,
|
||||
last_seen_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
)
|
||||
"""
|
||||
)
|
||||
|
||||
op.execute(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS public.images (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
fullres_image VARCHAR NOT NULL,
|
||||
preview_image VARCHAR NOT NULL,
|
||||
order_index INTEGER NOT NULL,
|
||||
car_id INTEGER NOT NULL REFERENCES public.cars(id) ON DELETE CASCADE
|
||||
)
|
||||
"""
|
||||
)
|
||||
|
||||
op.execute(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS public.sync_runs (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
started_at TIMESTAMPTZ NOT NULL,
|
||||
finished_at TIMESTAMPTZ NULL,
|
||||
status TEXT NOT NULL,
|
||||
lane TEXT NOT NULL,
|
||||
ids_fetched INTEGER NOT NULL DEFAULT 0,
|
||||
cars_upserted INTEGER NOT NULL DEFAULT 0,
|
||||
cars_failed INTEGER NOT NULL DEFAULT 0,
|
||||
images_upserted INTEGER NOT NULL DEFAULT 0,
|
||||
error_summary TEXT NULL
|
||||
)
|
||||
"""
|
||||
)
|
||||
|
||||
op.execute("CREATE INDEX IF NOT EXISTS ix_images_car_id ON public.images (car_id)")
|
||||
op.execute("CREATE INDEX IF NOT EXISTS ix_sync_runs_started_at ON public.sync_runs (started_at)")
|
||||
op.execute("CREATE INDEX IF NOT EXISTS ix_sync_runs_status ON public.sync_runs (status)")
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
# Compatibility-only migration for shared production databases.
|
||||
pass
|
||||
Reference in New Issue
Block a user