# Database Setup

Flyer Crawler uses PostgreSQL with several extensions for full-text search, geographic data, and UUID generation.

---

## Required Extensions

| Extension   | Purpose                                     |
| ----------- | ------------------------------------------- |
| `postgis`   | Geographic/spatial data for store locations |
| `pg_trgm`   | Trigram matching for fuzzy text search      |
| `uuid-ossp` | UUID generation for primary keys            |

---

## Database Users

This project uses **environment-specific database users** to isolate production and test environments:

| User                 | Database             | Purpose    |
| -------------------- | -------------------- | ---------- |
| `flyer_crawler_prod` | `flyer-crawler-prod` | Production |
| `flyer_crawler_test` | `flyer-crawler-test` | Testing    |

---

## Production Database Setup

### Step 1: Install PostgreSQL

```bash
sudo apt update
sudo apt install postgresql postgresql-contrib
```

### Step 2: Create Database and User

Switch to the postgres system user:

```bash
sudo -u postgres psql
```

Run the following SQL commands (replace `'a_very_strong_password'` with a secure password):

```sql
-- Create the production role
CREATE ROLE flyer_crawler_prod WITH LOGIN PASSWORD 'a_very_strong_password';

-- Create the production database
CREATE DATABASE "flyer-crawler-prod" WITH OWNER = flyer_crawler_prod;

-- Connect to the new database
\c "flyer-crawler-prod"

-- Grant schema privileges
ALTER SCHEMA public OWNER TO flyer_crawler_prod;
GRANT CREATE, USAGE ON SCHEMA public TO flyer_crawler_prod;

-- Install required extensions (must be done as superuser)
CREATE EXTENSION IF NOT EXISTS postgis;
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

-- Exit
\q
```

### Step 3: Apply the Schema

Navigate to your project directory and run:

```bash
psql -U flyer_crawler_prod -d "flyer-crawler-prod" -f sql/master_schema_rollup.sql
```

This creates all tables, functions, triggers, and seeds essential data (categories, master items).

### Step 4: Seed the Admin Account

Set the required environment variables and run the seed script:

```bash
export DB_USER=flyer_crawler_prod
export DB_PASSWORD=your_password
export DB_NAME="flyer-crawler-prod"
export DB_HOST=localhost

npx tsx src/db/seed_admin_account.ts
```

---

## Test Database Setup

The test database is used by CI/CD pipelines and local test runs.

### Step 1: Create the Test Database

```bash
sudo -u postgres psql
```

```sql
-- Create the test role
CREATE ROLE flyer_crawler_test WITH LOGIN PASSWORD 'a_very_strong_password';

-- Create the test database
CREATE DATABASE "flyer-crawler-test" WITH OWNER = flyer_crawler_test;

-- Connect to the test database
\c "flyer-crawler-test"

-- Grant schema privileges (required for test runner to reset schema)
ALTER SCHEMA public OWNER TO flyer_crawler_test;
GRANT CREATE, USAGE ON SCHEMA public TO flyer_crawler_test;

-- Install required extensions
CREATE EXTENSION IF NOT EXISTS postgis;
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

-- Exit
\q
```

### Step 2: Configure CI/CD Secrets

Ensure these secrets are set in your Gitea repository settings:

**Shared:**

| Secret    | Description                           |
| --------- | ------------------------------------- |
| `DB_HOST` | Database hostname (e.g., `localhost`) |
| `DB_PORT` | Database port (e.g., `5432`)          |

**Production-specific:**

| Secret             | Description                                     |
| ------------------ | ----------------------------------------------- |
| `DB_USER_PROD`     | Production database user (`flyer_crawler_prod`) |
| `DB_PASSWORD_PROD` | Production database password                    |
| `DB_DATABASE_PROD` | Production database name (`flyer-crawler-prod`) |

**Test-specific:**

| Secret             | Description                               |
| ------------------ | ----------------------------------------- |
| `DB_USER_TEST`     | Test database user (`flyer_crawler_test`) |
| `DB_PASSWORD_TEST` | Test database password                    |
| `DB_DATABASE_TEST` | Test database name (`flyer-crawler-test`) |

---

## How the Test Pipeline Works

The CI pipeline uses a permanent test database that gets reset on each test run:

1. **Setup**: The vitest global setup script connects to `flyer-crawler-test`
2. **Schema Reset**: Executes `sql/drop_tables.sql` (`DROP SCHEMA public CASCADE`)
3. **Schema Application**: Runs `sql/master_schema_rollup.sql` to build a fresh schema
4. **Test Execution**: Tests run against the clean database

This approach is faster than creating/destroying databases and doesn't require sudo access.

---

## Connecting to Production Database

```bash
psql -h localhost -U flyer_crawler_prod -d "flyer-crawler-prod" -W
```

---

## Checking PostGIS Version

```sql
SELECT version();
SELECT PostGIS_Full_Version();
```

Example output:

```text
PostgreSQL 14.19 (Ubuntu 14.19-0ubuntu0.22.04.1)
POSTGIS="3.2.0 c3e3cc0" GEOS="3.10.2-CAPI-1.16.0" PROJ="8.2.1"
```

---

## Schema Files

| File                           | Purpose                                                   |
| ------------------------------ | --------------------------------------------------------- |
| `sql/master_schema_rollup.sql` | Complete schema with all tables, functions, and seed data |
| `sql/drop_tables.sql`          | Drops entire schema (used by test runner)                 |
| `sql/schema.sql.txt`           | Legacy schema file (reference only)                       |

---

## Backup and Restore

### Create a Backup

```bash
pg_dump -U flyer_crawler_prod -d "flyer-crawler-prod" -F c -f backup.dump
```

### Restore from Backup

```bash
pg_restore -U flyer_crawler_prod -d "flyer-crawler-prod" -c backup.dump
```

---

## Related Documentation

- [Installation Guide](INSTALL.md) - Local development setup
- [Deployment Guide](DEPLOYMENT.md) - Production deployment
