Skip to content

Conversation

@ArnabChatterjee20k
Copy link
Contributor

@ArnabChatterjee20k ArnabChatterjee20k commented Jun 23, 2025

Summary by CodeRabbit

  • New Features

    • Added support for batch create-or-update (upsert) operations for documents, including permission synchronization.
    • Enabled upsert functionality in the Postgres adapter with tenant-aware conditional updates.
  • Bug Fixes

    • Corrected unique constraints and index creation in the Postgres adapter.
  • Refactor

    • Streamlined upsert logic by separating statement preparation from execution for improved maintainability.
  • Style

    • Improved code formatting and string concatenations for better readability.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 23, 2025

"""

Walkthrough

The changes refactor and centralize upsert (create-or-update) logic for SQL adapters. The MariaDB and Postgres adapters now provide a getUpsertStatement method to prepare upsert SQL statements. The SQL base class introduces an abstract getUpsertStatement and a new createOrUpdateDocuments method, moving permission and batch upsert handling from MariaDB into the shared base. Postgres upsert support is enabled, and collection uniqueness on _uid is enforced.

Changes

File(s) Change Summary
src/Database/Adapter/MariaDB.php Removed createOrUpdateDocuments; added getUpsertStatement for preparing upsert PDO statements.
src/Database/Adapter/Postgres.php Added getUpsertStatement; enabled upsert support; enforced _uid uniqueness; fixed formatting.
src/Database/Adapter/SQL.php Added abstract getUpsertStatement and new createOrUpdateDocuments with batch upsert and permission sync logic; minor formatting.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant SQLAdapter
    participant DB

    Client->>SQLAdapter: createOrUpdateDocuments(collection, attribute, changes)
    SQLAdapter->>SQLAdapter: Prepare attributes, permissions, and batch keys
    SQLAdapter->>SQLAdapter: getUpsertStatement(...)
    SQLAdapter->>DB: Execute upsert statement
    SQLAdapter->>DB: Execute permission removals/additions
    SQLAdapter->>DB: Fetch updated sequences (if needed)
    SQLAdapter-->>Client: Return updated Document objects
Loading

Estimated code review effort

File(s) Effort
src/Database/Adapter/MariaDB.php 2 (30–90 minutes)
src/Database/Adapter/Postgres.php 2 (30–90 minutes)
src/Database/Adapter/SQL.php 4 (240–360 minutes)

Poem

In the warren of code, upserts now shine bright,
With shared logic hopping from night into light.
Maria and Postgres, each with a plan,
SQL’s new methods—oh, what a span!
Permissions in sync, batch docs in a row,
The database garden continues to grow.
🐇✨
"""


📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7c40ce2 and f9805a2.

📒 Files selected for processing (3)
  • src/Database/Adapter/MariaDB.php (1 hunks)
  • src/Database/Adapter/Postgres.php (8 hunks)
  • src/Database/Adapter/SQL.php (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/Database/Adapter/Postgres.php
  • src/Database/Adapter/SQL.php
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: ArnabChatterjee20k
PR: utopia-php/database#613
File: src/Database/Adapter/Postgres.php:1254-1319
Timestamp: 2025-07-01T11:31:37.438Z
Learning: In PostgreSQL adapter methods like getUpsertStatement, complexity for database-specific SQL generation is acceptable when the main business logic is properly separated in the parent SQL adapter class, following the adapter pattern where each database adapter handles its own SQL syntax requirements.
src/Database/Adapter/MariaDB.php (1)

Learnt from: ArnabChatterjee20k
PR: #613
File: src/Database/Adapter/Postgres.php:1254-1319
Timestamp: 2025-07-01T11:31:37.438Z
Learning: In PostgreSQL adapter methods like getUpsertStatement, complexity for database-specific SQL generation is acceptable when the main business logic is properly separated in the parent SQL adapter class, following the adapter pattern where each database adapter handles its own SQL syntax requirements.

🔇 Additional comments (1)
src/Database/Adapter/MariaDB.php (1)

1153-1214: Excellent implementation of MariaDB-specific upsert statement generation.

The getUpsertStatement method correctly implements MariaDB's INSERT ... ON DUPLICATE KEY UPDATE syntax with proper tenant-aware handling for shared tables. The separation of SQL generation from execution follows the adapter pattern well, delegating business logic to the parent SQL class while keeping database-specific syntax isolated.

Key strengths:

  • Proper use of VALUES() function for both increment and update operations
  • Tenant-aware conditional updates using IF(_tenant = VALUES(_tenant), ...)
  • Correct parameter binding and escaping
  • Clean separation between statement preparation and execution
✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (3)
src/Database/Adapter/MariaDB.php (1)

1151-1166: Fix PHPDoc type hints for accuracy

The PHPDoc type hints appear to be inaccurate. The $attributes parameter likely contains mixed values (strings, integers, booleans, etc.), not just strings. Similarly, $bindValues is typed as array<mixed> which is correct, but $batchKeys might also need clarification.

     /**
      * @param string $tableName
      * @param string $columns
      * @param array<string> $batchKeys
-     * @param array<string> $attributes
+     * @param array<string, mixed> $attributes
      * @param array<mixed> $bindValues
      * @param string $attribute
      * @return mixed
      */
src/Database/Adapter/Postgres.php (1)

1256-1271: Fix PHPDoc type hints and consider return type

Similar to the MariaDB adapter, the PHPDoc type hints need adjustment. Also, the return type mixed could be more specific.

     /**
      * @param string $tableName
      * @param string $columns
      * @param array<string> $batchKeys
-     * @param array<string> $attributes
+     * @param array<string, mixed> $attributes
      * @param array<mixed> $bindValues
      * @param string $attribute
-     * @return mixed
+     * @return \PDOStatement
      */
     protected function getUpsertStatement(
         string $tableName,
         string $columns,
         array $batchKeys,
         array $attributes,
         array $bindValues,
         string $attribute = '',
-    ): mixed {
+    ): \PDOStatement {
src/Database/Adapter/SQL.php (1)

1924-2099: Consider breaking down this complex method.

The createOrUpdateDocuments method is 175 lines long with high cyclomatic complexity, handling multiple responsibilities including document preparation, upsert execution, and permission synchronization.

Consider extracting the permission synchronization logic (lines 2002-2081) into a separate protected method like synchronizePermissions(string $collection, array $changes) to improve readability and maintainability.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aa0116b and 22a5816.

📒 Files selected for processing (3)
  • src/Database/Adapter/MariaDB.php (1 hunks)
  • src/Database/Adapter/Postgres.php (8 hunks)
  • src/Database/Adapter/SQL.php (4 hunks)
🔇 Additional comments (6)
src/Database/Adapter/MariaDB.php (1)

1167-1213: Well-implemented UPSERT statement builder

The implementation is clean and well-structured:

  • Good use of closure for reusable update clause generation
  • Proper tenant isolation with conditional updates
  • Secure parameter binding prevents SQL injection
  • Clear separation between increment and full update modes
src/Database/Adapter/Postgres.php (4)

241-242: Good addition of UNIQUE constraint on _uid

Adding the UNIQUE constraint on _uid is essential for:

  • Ensuring document ID uniqueness at the database level
  • Enabling the UPSERT functionality with ON CONFLICT ("_uid")
  • Maintaining consistency with the MariaDB adapter

276-285: Fix for SQL string concatenation

Good catch fixing the string concatenation. The previous approach with string interpolation inside the SQL would have resulted in malformed SQL statements.


1272-1319: Well-implemented Postgres UPSERT with tenant isolation

The implementation correctly adapts the UPSERT logic for Postgres:

  • Proper use of ON CONFLICT ("_uid") DO UPDATE syntax
  • Correct usage of EXCLUDED pseudo-table for new values
  • Tenant-aware updates using CASE WHEN statements
  • Maintains feature parity with MariaDB adapter

2037-2040: Enable upsert support for Postgres

Correctly enables upsert support now that the getUpsertStatement method is implemented.

src/Database/Adapter/SQL.php (1)

1544-1544: LGTM!

Good formatting improvement for consistency.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (3)
src/Database/Adapter/SQL.php (3)

1398-1414: Fix PHPDoc syntax error and improve documentation.

The PHPDoc has a trailing comma that should be removed, and the parameter documentation needs improvement.


1944-1953: Clarify variable usage to avoid confusion.

The $attributes variable is initialized as an empty array at line 1944 but then overwritten in the loop at line 1953. This could lead to confusion about its purpose.


1975-1979: Fix incorrect PHPDoc comment.

The PHPDoc comment references the wrong variable name.

🧹 Nitpick comments (1)
src/Database/Adapter/SQL.php (1)

1924-2099: Consider refactoring this complex method for better maintainability.

This method is quite large (175 lines) and handles multiple responsibilities. The permission handling logic appears to be duplicated from other methods in the class.

Consider extracting helper methods for:

  • Permission difference calculation
  • Permission removal query building
  • Permission addition query building
  • Document attribute preparation

This would improve readability, reduce duplication, and make the code more testable.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 22a5816 and 2a8a6cb.

⛔ Files ignored due to path filters (2)
  • log.log is excluded by !**/*.log
  • log_pg.log is excluded by !**/*.log
📒 Files selected for processing (1)
  • src/Database/Adapter/SQL.php (4 hunks)
🔇 Additional comments (2)
src/Database/Adapter/SQL.php (2)

8-8: LGTM!

The import is correctly added for the Change class used in the new createOrUpdateDocuments method.


1544-1544: LGTM!

Good formatting improvement with consistent spacing around the concatenation operator.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 630329f and ebede51.

📒 Files selected for processing (1)
  • src/Database/Adapter/Postgres.php (9 hunks)
🧰 Additional context used
🪛 PHPMD (2.15.0)
src/Database/Adapter/Postgres.php

1271-1271: The method getUpsertStatement has a boolean flag argument $increment, which is a certain sign of a Single Responsibility Principle violation. (Clean Code Rules)

(BooleanArgumentFlag)


1275-1277: The method getUpsertStatement uses an else expression. Else clauses are basically not necessary and you can simplify the code by not using them. (Clean Code Rules)

(ElseExpression)


1294-1303: The method getUpsertStatement uses an else expression. Else clauses are basically not necessary and you can simplify the code by not using them. (Clean Code Rules)

(ElseExpression)

🔇 Additional comments (7)
src/Database/Adapter/Postgres.php (7)

148-150: LGTM - Clean formatting improvement.

The indentation fix improves code readability for the method chaining.


235-235: LGTM - Improved unique index creation.

The changes correctly implement explicit quoting for unique indexes on _uid (and _tenant for shared tables) instead of using LOWER(). This aligns with the past review comment about unique keys for shared tables requiring (_uid, _tenant).

Also applies to: 246-246, 253-253


275-275: LGTM - Consistent SQL formatting.

The formatting improvements enhance readability of the permission index creation statements.

Also applies to: 277-277, 282-282, 284-284


577-577: LGTM - Consistent indentation.

Minor formatting improvement for better code readability.


1528-1528: LGTM - Consistent formatting.

Minor improvement to ORDER BY clause formatting.


1811-1811: LGTM - Improved readability.

The spacing improvement makes the condition concatenation more readable.


2039-2039: LGTM - Enables upsert functionality.

This change activates the upsert support for Postgres, which is consistent with the new getUpsertStatement implementation. Ensure that the upsert functionality is thoroughly tested, especially the tenant isolation logic for shared tables.

@coderabbitai coderabbitai bot mentioned this pull request Jul 24, 2025
@abnegate abnegate merged commit a29d70d into utopia-php:main Jul 25, 2025
15 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Aug 6, 2025
This was referenced Aug 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants