- Add complete dark mode system with theme context and toggle - Implement dark mode toggle component in navigation menu - Add client-side routing with SSR-safe signal handling - Fix language selector styling for better dark mode compatibility - Add documentation system with mdBook integration - Improve navigation menu with proper external/internal link handling - Add comprehensive project documentation and configuration - Enhance theme system with localStorage persistence - Fix arena panic issues during server-side rendering - Add proper TypeScript configuration and build optimizations 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
7.2 KiB
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
- URL-Based Database Detection: The application automatically detects database type from the connection URL
- PostgreSQL Support: Full support for PostgreSQL with native SQL syntax
- SQLite Configuration: Configuration files support SQLite URLs
- Unified Codebase: Single codebase handles both database types
- Automatic Table Creation: Database tables are created automatically on startup
🔧 Current Limitations
- PostgreSQL-First Implementation: The current code uses PostgreSQL-specific SQL syntax
- SQLite Compatibility: While SQLx supports SQLite, the SQL queries use PostgreSQL syntax ($1, $2) instead of SQLite syntax (?1, ?2)
- 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:
// 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.
// Uses PgPool but can connect to SQLite URLs
PgPool::connect(database_url).await
Configuration Examples
PostgreSQL Configuration
[database]
url = "postgresql://username:password@localhost:5432/database_name"
max_connections = 10
min_connections = 1
SQLite Configuration
[database]
url = "sqlite:database.db"
max_connections = 10
min_connections = 1
Environment Variable Override
# PostgreSQL
export DATABASE_URL="postgresql://user:pass@localhost:5432/mydb"
# SQLite
export DATABASE_URL="sqlite:my_app.db"
Practical Usage
Quick Start with SQLite
export DATABASE_URL="sqlite:database.db"
cargo run --bin server
Quick Start with PostgreSQL
# 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
# 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:
pub enum DatabasePool {
Postgres(PgPool),
Sqlite(SqlitePool),
}
Option 2: Conditional Compilation
Use feature flags to compile for specific databases:
#[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
# 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
- Export data from SQLite
- Set up PostgreSQL instance
- Change
DATABASE_URL - Import data to PostgreSQL
- Restart application
From PostgreSQL to SQLite
- Export data from PostgreSQL
- Change
DATABASE_URLto SQLite - Restart application (tables created automatically)
- 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
# 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
- Use environment variables for database URLs in production
- Start with SQLite for development and testing
- Use PostgreSQL for production deployments
- Configure appropriate connection pools for your workload
- Monitor database performance and adjust settings
- Regular backups for production databases
- 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.