database icon indicating copy to clipboard operation
database copied to clipboard

Unique Exception

Open fogelito opened this issue 4 months ago β€’ 1 comments

Summary by CodeRabbit

  • New Features

    • Added a distinct Unique error type to represent non-primary unique-index violations.
  • Bug Fixes

    • Adapters now distinguish primary-identifier duplicates from other unique-index conflicts; non-primary conflicts surface as Unique errors.
    • Duplicate/error handling consolidated into a common processor for more consistent and clearer error reporting across databases.
    • Public API signatures unchanged.
  • Tests

    • End-to-end tests updated to accept and assert both Duplicate and Unique error outcomes.

fogelito avatar Oct 12 '25 06:10 fogelito

Walkthrough

Adds a new Utopia\Database\Exception\Unique class and updates MariaDB, Postgres, and SQLite adapters to parse DB-specific duplicate/unique constraint errors and map them to either DuplicateException or UniqueException; updates docblocks and e2e tests to accept both exception types.

Changes

Cohort / File(s) Summary
Exception: New type
src/Database/Exception/Unique.php
Adds Unique exception class in Utopia\Database\Exception, extending Duplicate.
Adapter: MariaDB
src/Database/Adapter/MariaDB.php
Imports Unique as UniqueException; updates docblocks (deleteIndex, createDocument, updateDocument) to include @throws UniqueException; processException inspects duplicate codes (23000/1062) and maps to DuplicateException for _uid/PRIMARY key names, otherwise to UniqueException.
Adapter: Postgres
src/Database/Adapter/Postgres.php
Imports Unique as UniqueException; processException parses duplicate constraint column names (23505 or translated 23000/19), compares against expected key sets (_uid or _tenant+_uid), and returns DuplicateException or UniqueException accordingly.
Adapter: SQLite
src/Database/Adapter/SQLite.php
Imports Unique as UniqueException; createDocument/updateDocument delegate PDOExceptions to processException($e); processException preserves timeout mapping and maps constraint violations to DuplicateException when targeting _tenant+_uid, otherwise to UniqueException.
Tests: e2e document scopes
tests/e2e/Adapter/Scopes/DocumentTests.php
Imports Unique as UniqueException; updates tests to accept either DuplicateException or UniqueException for duplicate/unique constraint failures, adjusting assertions accordingly.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Client
  participant Adapter as DB Adapter\n(MariaDB / Postgres / SQLite)
  participant DB as Database
  participant Handler as processException

  Client->>Adapter: createDocument/updateDocument(...)
  Adapter->>DB: INSERT/UPDATE
  DB-->>Adapter: PDOException / SQL error (duplicate)
  Adapter->>Handler: processException(error)
  alt Duplicate/Unique constraint detected
    note right of Handler #f0f4c3: Adapter-specific parsing\nMariaDB: key name (23000/1062)\nPostgres: column list (23505 or 23000/19)\nSQLite: constraint detail (23000/19)
    Handler-->>Adapter: DuplicateException or UniqueException
    Adapter-->>Client: throw mapped exception
  else Timeout or other mapped error
    Handler-->>Adapter: rethrow original or mapped timeout exception
    Adapter-->>Client: throw exception
  end

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • abnegate

Poem

I hop through rows and index trails,
A new Unique joins Duplicate's tales.
Maria, Postgres, SQLite debate,
Which constraint was truly at stake.
Tests nod along β€” the rabbit celebrates πŸ‡βœ¨

Pre-merge checks and finishing touches

βœ… Passed checks (3 passed)
Check name Status Explanation
Description Check βœ… Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check βœ… Passed The pull request title "Unique Exception" directly reflects the primary objective of the changeset, which is to introduce a new Unique exception class and update multiple database adapters (MariaDB, Postgres, SQLite) to distinguish between DuplicateException (for document ID duplicates) and UniqueException (for other unique constraint violations). The title is concise, clear, and accurately summarizes the main change without being vague or misleading. A developer scanning the git history would understand that this PR addresses exception handling for unique constraints.
Docstring Coverage βœ… Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • [ ] πŸ“ Generate docstrings
πŸ§ͺ Generate unit tests (beta)
  • [ ] Create PR with unit tests
  • [ ] Post copyable unit tests in a comment
  • [ ] Commit unit tests in branch unique-exception

πŸ“œ Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 6a9c42ab809189cb3023cfa23c992e6a870aaf61 and 968fff63dd423a92ac5684269d6207432e7ae9b3.

πŸ“’ Files selected for processing (2)
  • src/Database/Adapter/Postgres.php (2 hunks)
  • tests/e2e/Adapter/Scopes/DocumentTests.php (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/Database/Adapter/Postgres.php
  • tests/e2e/Adapter/Scopes/DocumentTests.php
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: Adapter Tests (SharedTables/SQLite)
  • GitHub Check: Adapter Tests (SharedTables/MySQL)
  • GitHub Check: Adapter Tests (Pool)
  • GitHub Check: Adapter Tests (SharedTables/Postgres)
  • GitHub Check: Adapter Tests (Mirror)
  • GitHub Check: Adapter Tests (Postgres)
  • GitHub Check: Adapter Tests (SharedTables/MariaDB)
  • GitHub Check: Adapter Tests (SQLite)
  • GitHub Check: Adapter Tests (MySQL)
  • GitHub Check: Adapter Tests (MariaDB)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

coderabbitai[bot] avatar Oct 12 '25 06:10 coderabbitai[bot]