Sangeetha-Grantha

Metadata Value
Status Active
Version 1.1.0
Last Updated 2026-09-10
Author Sangeetha Grantha Team
Document Type Design reference

Database Layer Optimization & Modernization


[!NOTE] Design/reference material: this page may include proposals or earlier implementation assumptions. Use current feature map for implemented behavior and current operating steps.

Implementation Date: 2025-01-27

Executive Summary

This feature optimizes the application’s Data Access Layer (DAL) by leveraging modern features of the Kotlin Exposed ORM framework. The primary goals are to reduce database round-trips, improve transaction efficiency, and eliminate anti-patterns like “Delete-Insert” for collection updates.

✅ All optimizations have been successfully implemented across all repositories.

Problem Statement

The previous implementation of the DAL suffered from several inefficiencies:

  1. Delete-Insert Anti-Pattern: Updating child collections (e.g., KrithiSections) involved deleting all existing records and re-inserting the new set. This caused:
    • Loss of metadata (e.g., original created_at timestamps).
    • Unnecessary expansion of transaction logs.
    • Potential indexing churn.
  2. Multiple Round-Trips: Operations like create and update required two separate database queries: one to perform the action and another to SELECT the resulting entity to return to the caller. This doubled the network latency for these critical operations.

Solution Implemented

1. Smart Collection Updates (Delta Updates) ✅ COMPLETED

Collection management has been refactored to implement a smart diffing algorithm:

Implemented in:

Benefits:

2. Single Round-Trip Persistence (Exposed Returning) ✅ COMPLETED

All repositories now utilize RETURNING clause capabilities to perform writes and reads in a single query.

Implementation Pattern:

Repositories Optimized:

  1. UserRepository - create(), update()
  2. KrithiRepository - create(), update(), createLyricVariant(), updateLyricVariant()
  3. ImportRepository - createImport(), reviewImport()
  4. ComposerRepository - create(), update()
  5. RagaRepository - create(), update()
  6. TalaRepository - create(), update()
  7. TempleRepository - create(), update()
  8. TagRepository - create(), update()
  9. KrithiNotationRepository - createVariant(), updateVariant(), createRow(), updateRow()

Code Pattern Example:

// Create with RETURNING
suspend fun create(...): EntityDto = DatabaseFactory.dbQuery {
    EntityTable.insert {
        // ... field assignments
    }
        .resultedValues
        ?.single()
        ?.toEntityDto()
        ?: error("Failed to insert entity")
}

// Update with RETURNING
suspend fun update(id: Uuid, ...): EntityDto? = DatabaseFactory.dbQuery {
    EntityTable
        .updateReturning(
            where = { EntityTable.id eq id.toJavaUuid() }
        ) {
            // ... field updates
        }
        .singleOrNull()
        ?.toEntityDto()
}

Technical Requirements

Impact Analysis

Performance Improvements ✅ ACHIEVED

Data Integrity ✅ ACHIEVED

Code Quality ✅ ACHIEVED

Implementation Details

Before Optimization

// Two queries: INSERT + SELECT
KrithisTable.insert { ... }
KrithisTable.selectAll().where { ... }.single()

After Optimization

// Single query: INSERT with RETURNING
KrithisTable.insert { ... }
    .resultedValues
    ?.single()
    ?.toKrithiDto()

Before Optimization

// Two queries: UPDATE + SELECT
KrithisTable.update { ... }
KrithisTable.selectAll().where { ... }.singleOrNull()

After Optimization

// Single query: UPDATE with RETURNING
KrithisTable.updateReturning(where = { ... }) { ... }
    .singleOrNull()
    ?.toKrithiDto()

Testing


Section index · Documentation home · Feature status