komga/ai-docs/postgresql-migration-summary.md
duong.doan1 29692c738b feat: Complete Sprint 1 PostgreSQL infrastructure
- Add flyway-database-postgresql dependency
- Create DatabaseUdfProvider abstraction with SQLite/PostgreSQL implementations
- Update all DAO classes to use JooqUdfHelper for database-agnostic UDF/collation
- Implement dynamic JOOQ dialect configuration based on database type
- Add PostgreSQL migration directory with initial migration
- Create Docker Compose setup for PostgreSQL 16
- Add integration test with Testcontainers PostgreSQL
- Create helper scripts for local testing
- Update application.yml for simplified testing
- Add documentation and task tracking
2026-04-07 14:09:19 +07:00

5.8 KiB

PostgreSQL Migration - Sprint 1 Summary

Mục tiêu

Implement PostgreSQL database support cho Komga while maintaining backward compatibility với SQLite.

Kiến trúc đã triển khai

1. Database Abstraction Layer

  • DatabaseType enum: SQLITE, POSTGRESQL
  • DatabaseUdfProvider interface: Abstract UDF/collation functions
    • SqliteUdfProvider: SQLite implementation (REGEXP, UDF_STRIP_ACCENTS, COLLATION_UNICODE_3)
    • PostgresUdfProvider: PostgreSQL implementation (pg_trgm, unaccent extension)
  • JooqUdfHelper: Spring component cung cấp database-agnostic extension methods

2. Cấu hình DataSource

  • DataSourcesConfiguration: Tạo DataSource dựa trên database type
  • Dynamic JOOQ dialect: KomgaJooqConfiguration sử dụng SQLDialect động
  • Flyway vendor detection: Tự động sử dụng {vendor} directory (sqlite/postgresql)

3. Migration Strategy

  • Two-phase bean registration: Sprint 1 tập trung infrastructure, UDF implementations có thể stub
  • Backward compatibility: SQLite vẫn là default
  • Tasks database: Giữ nguyên SQLite cho tasks database (đơn giản hóa Sprint 1)

Các file đã tạo/sửa

Created:

  • komga/src/flyway/resources/db/migration/postgresql/V20200706141854__initial_migration.sql
  • komga/src/main/kotlin/org/gotson/komga/infrastructure/datasource/DatabaseType.kt
  • komga/src/main/kotlin/org/gotson/komga/infrastructure/datasource/DatabaseUdfProvider.kt
  • komga/src/main/kotlin/org/gotson/komga/infrastructure/datasource/DatabaseUdfProviderConfiguration.kt
  • komga/src/main/kotlin/org/gotson/komga/infrastructure/datasource/PostgresUdfProvider.kt
  • komga/src/main/kotlin/org/gotson/komga/infrastructure/datasource/SqliteUdfProvider.kt
  • komga/src/main/kotlin/org/gotson/komga/infrastructure/jooq/JooqUdfHelper.kt

Modified DAO classes:

  • BookDtoDao.kt: Added jooqUdfHelper constructor parameter, updated sorts map
  • SeriesDtoDao.kt: Added jooqUdfHelper constructor parameter, updated sorts map
  • ReadListDao.kt: Added jooqUdfHelper constructor parameter, updated sorts map
  • SeriesCollectionDao.kt: Added jooqUdfHelper constructor parameter, updated sorts map
  • ReferentialDao.kt: Updated all 28 references to use jooqUdfHelper

Helper classes:

  • SeriesSearchHelper.kt: Added jooqUdfHelper parameter, updated UDF references
  • BookSearchHelper.kt: Added jooqUdfHelper parameter, updated UDF references

Configuration:

  • KomgaJooqConfiguration.kt: Updated to use dynamic SQLDialect
  • DataSourcesConfiguration.kt: Already had PostgreSQL support
  • KomgaProperties.kt: Already had database type/URL fields

Cấu hình PostgreSQL

Application Properties:

komga:
  database:
    type: postgresql
    url: jdbc:postgresql://localhost:5432/komga
    username: komga
    password: komga123
  tasks-db:
    file: ${komga.config-dir}/tasks.sqlite  # Vẫn dùng SQLite cho tasks

PostgreSQL Extensions cần thiết:

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pg_trgm";     -- For text search/pattern matching
CREATE EXTENSION IF NOT EXISTS "unaccent";    -- For accent removal (similar to UDF_STRIP_ACCENTS)

Docker Setup

docker-compose.yml:

services:
  postgres:
    image: postgres:16-alpine
    ports: ["5433:5432"]  # Port 5433 để tránh conflict với local PostgreSQL
    environment:
      POSTGRES_DB: komga
      POSTGRES_USER: komga
      POSTGRES_PASSWORD: komga123
    volumes:
      - ./docker/postgres/init.sql:/docker-entrypoint-initdb.d/init.sql

Scripts:

  • run-local-with-postgres.sh: Chạy backend với PostgreSQL
  • run-test-with-docker.sh: Chạy tests với Testcontainers PostgreSQL
  • test-postgresql.sh: Script test tổng quát

Testing

Integration Test:

@Testcontainers
@SpringBootTest
@ActiveProfiles("test")
class PostgreSQLIntegrationTest {
    @Container
    val postgres = PostgreSQLContainer("postgres:16-alpine")
    
    @Test
    fun `should connect to PostgreSQL database`() {
        // Test database connection
    }
    
    @Test  
    fun `should use PostgreSQL UDF provider`() {
        // Test UDF provider selection
    }
}

UDF/Collation Mapping

SQLite → PostgreSQL:

  • REGEXP → PostgreSQL regex operators (~, ~*)
  • UDF_STRIP_ACCENTSunaccent() function
  • COLLATION_UNICODE_3COLLATE "C" hoặc custom collation

JooqUdfHelper methods:

class JooqUdfHelper(
    private val databaseUdfProvider: DatabaseUdfProvider
) {
    fun <T> Field<T>.collateUnicode3(): Field<T> = 
        databaseUdfProvider.collateUnicode3(this)
    
    fun Field<String>.stripAccents(): Field<String> =
        databaseUdfProvider.stripAccents(this)
    
    fun Field<String>.likeRegex(pattern: String): Condition =
        databaseUdfProvider.likeRegex(this, pattern)
}

Các bước tiếp theo (Sprint 2)

  1. Complete UDF implementations: Hoàn thiện PostgresUdfProvider implementations
  2. JOOQ code generation: Tạo JOOQ code cho PostgreSQL schema
  3. Comprehensive testing: Test tất cả API endpoints với PostgreSQL
  4. Performance optimization: Tối ưu queries cho PostgreSQL
  5. Documentation: Hướng dẫn migration từ SQLite sang PostgreSQL

Status hiện tại

Build thành công với SQLite
Backend khởi động và chạy Flyway migrations
PostgreSQL infrastructure đã sẵn sàng
Docker setup hoàn chỉnh
Integration tests cần chạy với Testcontainers

Lưu ý quan trọng

  • Backward compatibility: SQLite vẫn là default database
  • Tasks database: Vẫn dùng SQLite cho đơn giản
  • Flyway: Tự động detect vendor và sử dụng migration directory phù hợp
  • JOOQ: Runtime dialect dynamic, code generation vẫn dùng SQLite (Sprint 2 sẽ update)