- Add migration 021_location_hierarchy.sql with new table structure - Add location-loader.js seeder to import SQL dumps - Update all seeder files to use country_id instead of region_id - Rename companies.region_id to country_id
158 lines
6 KiB
SQL
158 lines
6 KiB
SQL
-- Migration: 021_location_hierarchy.sql
|
|
-- Description: Restructure location tables to use comprehensive geographic hierarchy
|
|
-- Data Source: GeoDB Cities (https://github.com/dr5hn/countries-states-cities-database)
|
|
|
|
-- ============================================================================
|
|
-- PHASE 1: Backup existing tables
|
|
-- ============================================================================
|
|
|
|
-- Rename old tables to preserve data
|
|
ALTER TABLE IF EXISTS regions RENAME TO regions_old;
|
|
ALTER TABLE IF EXISTS cities RENAME TO cities_old;
|
|
|
|
-- Drop old indexes (they will conflict)
|
|
DROP INDEX IF EXISTS idx_regions_country;
|
|
DROP INDEX IF EXISTS idx_cities_region;
|
|
|
|
-- ============================================================================
|
|
-- PHASE 2: Create new location hierarchy
|
|
-- ============================================================================
|
|
|
|
-- 2.1 Continents (formerly "regions" in GeoDB)
|
|
CREATE TABLE IF NOT EXISTS continents (
|
|
id BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
|
|
name VARCHAR(100) NOT NULL,
|
|
translations TEXT,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
flag SMALLINT DEFAULT 1 NOT NULL,
|
|
wiki_data_id VARCHAR(255)
|
|
);
|
|
|
|
COMMENT ON TABLE continents IS 'Geographic continents (Africa, Americas, Asia, Europe, Oceania, Polar)';
|
|
|
|
-- 2.2 Subregions (e.g., Northern Africa, South America)
|
|
CREATE TABLE IF NOT EXISTS subregions (
|
|
id BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
|
|
name VARCHAR(100) NOT NULL,
|
|
continent_id BIGINT NOT NULL REFERENCES continents(id),
|
|
translations TEXT,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
flag SMALLINT DEFAULT 1 NOT NULL,
|
|
wiki_data_id VARCHAR(255)
|
|
);
|
|
|
|
CREATE INDEX idx_subregions_continent ON subregions(continent_id);
|
|
COMMENT ON TABLE subregions IS 'Geographic subregions within continents';
|
|
|
|
-- 2.3 Countries
|
|
CREATE TABLE IF NOT EXISTS countries (
|
|
id BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
|
|
name VARCHAR(100) NOT NULL,
|
|
iso2 CHAR(2),
|
|
iso3 CHAR(3),
|
|
numeric_code CHAR(3),
|
|
phonecode VARCHAR(255),
|
|
capital VARCHAR(255),
|
|
currency VARCHAR(255),
|
|
currency_name VARCHAR(255),
|
|
currency_symbol VARCHAR(255),
|
|
tld VARCHAR(255),
|
|
native VARCHAR(255),
|
|
continent_id BIGINT REFERENCES continents(id),
|
|
subregion_id BIGINT REFERENCES subregions(id),
|
|
nationality VARCHAR(255),
|
|
latitude DECIMAL(10,8),
|
|
longitude DECIMAL(11,8),
|
|
emoji VARCHAR(10),
|
|
emoji_u VARCHAR(50),
|
|
timezones TEXT,
|
|
translations TEXT,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
flag SMALLINT DEFAULT 1 NOT NULL,
|
|
wiki_data_id VARCHAR(255)
|
|
);
|
|
|
|
CREATE INDEX idx_countries_iso2 ON countries(iso2);
|
|
CREATE INDEX idx_countries_iso3 ON countries(iso3);
|
|
CREATE INDEX idx_countries_continent ON countries(continent_id);
|
|
CREATE INDEX idx_countries_subregion ON countries(subregion_id);
|
|
COMMENT ON TABLE countries IS 'All countries with ISO codes, currencies, and metadata';
|
|
|
|
-- 2.4 States/Provinces
|
|
CREATE TABLE IF NOT EXISTS states (
|
|
id BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
|
|
name VARCHAR(255) NOT NULL,
|
|
country_id BIGINT NOT NULL REFERENCES countries(id),
|
|
country_code CHAR(2) NOT NULL,
|
|
iso2 VARCHAR(10),
|
|
fips_code VARCHAR(255),
|
|
type VARCHAR(191),
|
|
latitude DECIMAL(10,8),
|
|
longitude DECIMAL(11,8),
|
|
timezone VARCHAR(255),
|
|
translations TEXT,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
flag SMALLINT DEFAULT 1 NOT NULL,
|
|
wiki_data_id VARCHAR(255)
|
|
);
|
|
|
|
CREATE INDEX idx_states_country ON states(country_id);
|
|
CREATE INDEX idx_states_country_code ON states(country_code);
|
|
CREATE INDEX idx_states_iso2 ON states(iso2);
|
|
COMMENT ON TABLE states IS 'States, provinces, and administrative regions';
|
|
|
|
-- 2.5 Cities
|
|
CREATE TABLE IF NOT EXISTS cities (
|
|
id BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
|
|
name VARCHAR(255) NOT NULL,
|
|
state_id BIGINT NOT NULL REFERENCES states(id),
|
|
state_code VARCHAR(255),
|
|
country_id BIGINT NOT NULL REFERENCES countries(id),
|
|
country_code CHAR(2) NOT NULL,
|
|
latitude DECIMAL(10,8) NOT NULL,
|
|
longitude DECIMAL(11,8) NOT NULL,
|
|
population BIGINT,
|
|
timezone VARCHAR(255),
|
|
translations TEXT,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
flag SMALLINT DEFAULT 1 NOT NULL,
|
|
wiki_data_id VARCHAR(255)
|
|
);
|
|
|
|
CREATE INDEX idx_cities_state ON cities(state_id);
|
|
CREATE INDEX idx_cities_country ON cities(country_id);
|
|
CREATE INDEX idx_cities_country_code ON cities(country_code);
|
|
CREATE INDEX idx_cities_population ON cities(population);
|
|
COMMENT ON TABLE cities IS 'Cities with coordinates and population data';
|
|
|
|
-- ============================================================================
|
|
-- PHASE 3: Update companies table FKs
|
|
-- ============================================================================
|
|
|
|
-- Drop old FK constraint if exists (ignore errors)
|
|
ALTER TABLE companies DROP CONSTRAINT IF EXISTS companies_region_id_fkey;
|
|
ALTER TABLE companies DROP CONSTRAINT IF EXISTS companies_city_id_fkey;
|
|
|
|
-- Update column types to BIGINT (to match new tables)
|
|
ALTER TABLE companies ALTER COLUMN region_id TYPE BIGINT USING region_id::BIGINT;
|
|
ALTER TABLE companies ALTER COLUMN city_id TYPE BIGINT USING city_id::BIGINT;
|
|
|
|
-- Rename region_id to country_id for clarity
|
|
ALTER TABLE companies RENAME COLUMN region_id TO country_id;
|
|
|
|
-- Add new FK constraints (without REFERENCES for now - data will be populated by seeder)
|
|
-- These will be validated after seeder populates the data
|
|
|
|
-- Update indexes
|
|
DROP INDEX IF EXISTS idx_companies_region;
|
|
CREATE INDEX idx_companies_country ON companies(country_id);
|
|
CREATE INDEX idx_companies_city ON companies(city_id);
|
|
|
|
-- Add comments
|
|
COMMENT ON COLUMN companies.country_id IS 'Reference to countries table';
|
|
COMMENT ON COLUMN companies.city_id IS 'Reference to cities table';
|