# Database Support Summary

This document summarizes the database support implementation in the Rust application, which supports both PostgreSQL and SQLite databases based on the connection URL.

## Current Implementation Status

### ✅ What Works

1. **URL-Based Database Detection**: The application automatically detects database type from the connection URL
2. **PostgreSQL Support**: Full support for PostgreSQL with native SQL syntax
3. **SQLite Configuration**: Configuration files support SQLite URLs
4. **Unified Codebase**: Single codebase handles both database types
5. **Automatic Table Creation**: Database tables are created automatically on startup

### 🔧 Current Limitations

1. **PostgreSQL-First Implementation**: The current code uses PostgreSQL-specific SQL syntax
2. **SQLite Compatibility**: While SQLx supports SQLite, the SQL queries use PostgreSQL syntax ($1, $2) instead of SQLite syntax (?1, ?2)
3. **Type Handling**: Uses PostgreSQL-specific types (UUID, TIMESTAMPTZ, JSONB)

## How It Works

### Database Connection

The application detects the database type from the `DATABASE_URL` environment variable:

```rust
// In server/src/main.rs
let db_type = if database_url.starts_with("postgres://") 
    || database_url.starts_with("postgresql://") {
    "PostgreSQL"
} else if database_url.starts_with("sqlite:") {
    "SQLite"
} else {
    "Unknown"
};
```

### Current Database Pool

The application currently uses `PgPool` throughout, which works with PostgreSQL URLs directly and can be configured to work with SQLite through SQLx's compatibility layer.

```rust
// Uses PgPool but can connect to SQLite URLs
PgPool::connect(database_url).await
```

## Configuration Examples

### PostgreSQL Configuration
```toml
[database]
url = "postgresql://username:password@localhost:5432/database_name"
max_connections = 10
min_connections = 1
```

### SQLite Configuration
```toml
[database]
url = "sqlite:database.db"
max_connections = 10
min_connections = 1
```

### Environment Variable Override
```bash
# PostgreSQL
export DATABASE_URL="postgresql://user:pass@localhost:5432/mydb"

# SQLite
export DATABASE_URL="sqlite:my_app.db"
```

## Practical Usage

### Quick Start with SQLite
```bash
export DATABASE_URL="sqlite:database.db"
cargo run --bin server
```

### Quick Start with PostgreSQL
```bash
# Start PostgreSQL with Docker
docker run -d --name postgres -e POSTGRES_PASSWORD=password -p 5432:5432 postgres:15

# Connect to it
export DATABASE_URL="postgresql://postgres:password@localhost:5432/postgres"
cargo run --bin server
```

### Switching Between Databases
```bash
# Start with SQLite
export DATABASE_URL="sqlite:test.db"
cargo run --bin server

# Stop server (Ctrl+C), switch to PostgreSQL
export DATABASE_URL="postgresql://localhost:5432/mydb"
cargo run --bin server
```

## Implementation Architecture

### Current Structure
```
├── server/src/main.rs           # Database connection logic
├── server/src/auth/repository.rs   # Authentication database operations
├── server/src/content/repository.rs # Content management database operations
└── server/src/auth/two_factor.rs   # 2FA database operations
```

### Database Abstraction Pattern
The code currently uses a direct `PgPool` approach with PostgreSQL syntax, but is structured to allow for database-specific implementations in the future.

## Future Enhancement Options

### Option 1: Full Database Abstraction (Recommended)
Create a `DatabasePool` enum that handles both database types with appropriate SQL syntax:

```rust
pub enum DatabasePool {
    Postgres(PgPool),
    Sqlite(SqlitePool),
}
```

### Option 2: Conditional Compilation
Use feature flags to compile for specific databases:

```rust
#[cfg(feature = "postgres")]
use sqlx::PgPool as DbPool;
#[cfg(feature = "sqlite")]
use sqlx::SqlitePool as DbPool;
```

### Option 3: SQLx Any Driver
Use SQLx's `Any` driver for complete database agnosticism (with some type limitations).

## Database Schema Compatibility

### PostgreSQL Schema Features
- UUID primary keys with `gen_random_uuid()`
- TIMESTAMPTZ for timestamps
- JSONB for JSON data
- Advanced indexing

### SQLite Equivalent Features
- TEXT UUIDs with custom generation
- DATETIME for timestamps  
- TEXT for JSON storage
- Standard indexing

## Performance Considerations

### PostgreSQL
- **Best for**: Production, multi-user, high concurrency
- **Features**: Full ACID, advanced indexing, network access
- **Connection Pool**: 10-50 connections typical

### SQLite
- **Best for**: Development, testing, single-user apps
- **Features**: File-based, zero configuration, embedded
- **Connection Pool**: 1 connection recommended

## Security Considerations

### PostgreSQL
- Network security (firewall, VPN)
- Authentication (strong passwords, SSL)
- Authorization (role-based access)
- Regular security updates

### SQLite
- File system permissions (600/640)
- Backup encryption
- Access control at application level

## Testing Strategy

### Unit Tests
```bash
# PostgreSQL tests
export DATABASE_URL="postgresql://localhost/test_db"
cargo test

# SQLite tests  
export DATABASE_URL="sqlite::memory:"
cargo test
```

### Integration Tests
The application includes integration tests that can run against both database types by setting the appropriate `DATABASE_URL`.

## Migration Strategy

### From SQLite to PostgreSQL
1. Export data from SQLite
2. Set up PostgreSQL instance
3. Change `DATABASE_URL`
4. Import data to PostgreSQL
5. Restart application

### From PostgreSQL to SQLite
1. Export data from PostgreSQL
2. Change `DATABASE_URL` to SQLite
3. Restart application (tables created automatically)
4. Import data to SQLite

## Troubleshooting

### Common Issues

**"spawn_local called from outside of a task::LocalSet"**
- ✅ Fixed: The application uses proper LocalSet configuration

**Database connection failed**
- Check if database server is running
- Verify connection string format
- Check network access and credentials

**Table creation errors**
- Ensure database user has CREATE privileges
- Check for existing incompatible tables
- Review logs for specific SQL errors

### Debug Commands

```bash
# Test database connection
psql $DATABASE_URL -c "SELECT 1;"  # PostgreSQL
sqlite3 database.db "SELECT 1;"    # SQLite

# Check application logs
RUST_LOG=debug cargo run --bin server
```

## Best Practices

1. **Use environment variables** for database URLs in production
2. **Start with SQLite** for development and testing
3. **Use PostgreSQL** for production deployments
4. **Configure appropriate connection pools** for your workload
5. **Monitor database performance** and adjust settings
6. **Regular backups** for production databases
7. **Test migrations** on both database types if needed

## Conclusion

The current implementation provides a solid foundation for supporting both PostgreSQL and SQLite databases. While the code currently uses PostgreSQL syntax throughout, the architecture is designed to accommodate both databases through URL-based configuration.

For most use cases:
- **Development**: Use SQLite for simplicity
- **Production**: Use PostgreSQL for scalability and features
- **Testing**: Use in-memory SQLite for speed

The database choice can be changed at any time by simply updating the `DATABASE_URL`, making it easy to evolve your database strategy as your application grows.