- 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>
259 lines
7.2 KiB
Markdown
259 lines
7.2 KiB
Markdown
# 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. |