# Gas Stations Feature - Database Migration Guide

## Overview

Complete guide for running and verifying database migrations for the Gas Stations feature. Migrations create the necessary tables, indexes, and constraints for station caching and user favorites.

## Migration Files

Location: `/backend/src/features/stations/migrations/`

### 001_create_stations_tables.sql

Creates two tables:
- `station_cache`: Temporary storage for Google Places API results
- `saved_stations`: User's favorite stations with metadata

### 002_add_indexes.sql

Adds performance indexes:
- `idx_station_cache_place_id`: Fast lookups by Google Place ID
- `idx_station_cache_created_at`: Efficient cache cleanup queries
- `idx_saved_stations_user_id`: Fast user-scoped queries
- `idx_saved_stations_place_id`: Fast station lookups
- `idx_saved_stations_deleted_at`: Efficient soft delete filtering

## Running Migrations

### Prerequisites

- PostgreSQL database accessible
- Database connection configured
- Backend container running

### Run All Migrations

```bash
# In Docker environment
docker compose exec mvp-backend npm run migrate

# Or from backend directory
cd backend
npm run migrate
```

### Run Specific Migration

```bash
# Run only stations migrations
docker compose exec mvp-backend \
  psql $DATABASE_URL -f /app/src/features/stations/migrations/001_create_stations_tables.sql

docker compose exec mvp-backend \
  psql $DATABASE_URL -f /app/src/features/stations/migrations/002_add_indexes.sql
```

## Verification Steps

### 1. Verify Tables Created

```bash
docker compose exec postgres psql -U postgres -d motovaultpro -c "\dt station*"
```

**Expected Output**:
```
              List of relations
 Schema |      Name       | Type  |  Owner
--------+-----------------+-------+----------
 public | station_cache   | table | postgres
 public | saved_stations  | table | postgres
(2 rows)
```

### 2. Verify Table Structure

**station_cache**:
```bash
docker compose exec postgres psql -U postgres -d motovaultpro -c "\d station_cache"
```

**Expected Output**:
```
                      Table "public.station_cache"
   Column    |            Type             | Collation | Nullable | Default
-------------+-----------------------------+-----------+----------+---------
 id          | uuid                        |           | not null | uuid_generate_v4()
 place_id    | character varying(255)      |           | not null |
 name        | character varying(255)      |           | not null |
 address     | character varying(500)      |           |          |
 latitude    | numeric(10,8)               |           | not null |
 longitude   | numeric(11,8)               |           | not null |
 rating      | numeric(2,1)                |           |          |
 photo_url   | text                        |           |          |
 created_at  | timestamp without time zone |           |          | CURRENT_TIMESTAMP
Indexes:
    "station_cache_pkey" PRIMARY KEY, btree (id)
    "station_cache_place_id_key" UNIQUE CONSTRAINT, btree (place_id)
    "idx_station_cache_created_at" btree (created_at)
    "idx_station_cache_place_id" btree (place_id)
```

**saved_stations**:
```bash
docker compose exec postgres psql -U postgres -d motovaultpro -c "\d saved_stations"
```

**Expected Output**:
```
                      Table "public.saved_stations"
    Column    |            Type             | Collation | Nullable | Default
--------------+-----------------------------+-----------+----------+---------
 id           | uuid                        |           | not null | uuid_generate_v4()
 user_id      | character varying(255)      |           | not null |
 place_id     | character varying(255)      |           | not null |
 nickname     | character varying(255)      |           |          |
 notes        | text                        |           |          |
 is_favorite  | boolean                     |           |          | false
 created_at   | timestamp without time zone |           |          | CURRENT_TIMESTAMP
 updated_at   | timestamp without time zone |           |          | CURRENT_TIMESTAMP
 deleted_at   | timestamp without time zone |           |          |
Indexes:
    "saved_stations_pkey" PRIMARY KEY, btree (id)
    "saved_stations_user_id_place_id_key" UNIQUE CONSTRAINT, btree (user_id, place_id)
    "idx_saved_stations_deleted_at" btree (deleted_at)
    "idx_saved_stations_place_id" btree (place_id)
    "idx_saved_stations_user_id" btree (user_id)
```

### 3. Verify Indexes Created

```bash
docker compose exec postgres psql -U postgres -d motovaultpro -c "
  SELECT
    tablename,
    indexname,
    indexdef
  FROM pg_indexes
  WHERE tablename LIKE 'station%'
  ORDER BY tablename, indexname;
"
```

**Expected Output**: Lists all indexes for station_cache and saved_stations tables.

### 4. Test Insert Operations

**Insert into station_cache**:
```bash
docker compose exec postgres psql -U postgres -d motovaultpro <<EOF
INSERT INTO station_cache (place_id, name, address, latitude, longitude, rating)
VALUES (
  'test-place-id-123',
  'Test Shell Station',
  '123 Test St, San Francisco, CA',
  37.7749,
  -122.4194,
  4.2
);
SELECT * FROM station_cache WHERE place_id = 'test-place-id-123';
EOF
```

**Insert into saved_stations**:
```bash
docker compose exec postgres psql -U postgres -d motovaultpro <<EOF
INSERT INTO saved_stations (user_id, place_id, nickname, is_favorite)
VALUES (
  'test-user-123',
  'test-place-id-123',
  'My Test Station',
  true
);
SELECT * FROM saved_stations WHERE user_id = 'test-user-123';
EOF
```

### 5. Test Constraints

**Test UNIQUE constraint on saved_stations**:
```bash
docker compose exec postgres psql -U postgres -d motovaultpro <<EOF
-- First insert should succeed
INSERT INTO saved_stations (user_id, place_id) VALUES ('user-1', 'place-1');

-- Second insert with same user_id + place_id should fail
INSERT INTO saved_stations (user_id, place_id) VALUES ('user-1', 'place-1');
EOF
```

**Expected**: Second insert fails with "duplicate key value violates unique constraint"

### 6. Clean Up Test Data

```bash
docker compose exec postgres psql -U postgres -d motovaultpro <<EOF
DELETE FROM saved_stations WHERE user_id LIKE 'test-%';
DELETE FROM station_cache WHERE place_id LIKE 'test-%';
EOF
```

## Rollback Procedure

If migrations need to be reverted:

### Manual Rollback

```bash
docker compose exec postgres psql -U postgres -d motovaultpro <<EOF
-- Drop tables (cascades to all constraints and indexes)
DROP TABLE IF EXISTS saved_stations CASCADE;
DROP TABLE IF EXISTS station_cache CASCADE;
EOF
```

### Verify Rollback

```bash
docker compose exec postgres psql -U postgres -d motovaultpro -c "\dt station*"
```

**Expected**: "Did not find any relations"

## Migration Version Tracking

MotoVaultPro does not currently use a migration tracking table. Migrations are applied manually and tracked via git commit history.

**Future Enhancement**: Consider adding migration tracking table:
```sql
CREATE TABLE IF NOT EXISTS schema_migrations (
  version VARCHAR(255) PRIMARY KEY,
  applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```

## Troubleshooting

### Migration Fails with "uuid_generate_v4 does not exist"

**Cause**: PostgreSQL extension not enabled

**Solution**:
```bash
docker compose exec postgres psql -U postgres -d motovaultpro -c "CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\";"
```

### Migration Fails with "permission denied"

**Cause**: Database user lacks CREATE TABLE permission

**Solution**:
```bash
docker compose exec postgres psql -U postgres <<EOF
GRANT CREATE ON SCHEMA public TO your_db_user;
EOF
```

### Table Already Exists

**Cause**: Migrations run multiple times

**Solution**: Drop and recreate tables (see Rollback Procedure)

### Index Creation Slow

**Cause**: Large dataset or concurrent operations

**Solution**: Create indexes with `CONCURRENTLY` option:
```sql
CREATE INDEX CONCURRENTLY idx_name ON table_name (column_name);
```

## Performance Notes

- Indexes are created AFTER table creation for optimal performance
- station_cache uses auto-cleanup (scheduled job), not manual deletion
- saved_stations uses soft deletes (deleted_at) for referential integrity
- All indexes are B-tree for standard query performance

## References

- Architecture: `/backend/src/features/stations/docs/ARCHITECTURE.md`
- Database Schema: `/backend/src/features/stations/README.md#database-schema`
- Deployment Checklist: `/backend/src/features/stations/docs/deployment/DEPLOYMENT-CHECKLIST.md`
