Skip to content

Conversation

@fogelito
Copy link
Contributor

@fogelito fogelito commented Jul 24, 2025

Summary by CodeRabbit

  • New Features

    • Improved document update performance by skipping permission updates when no changes are detected in permissions.
  • Bug Fixes

    • Prevented unnecessary permission updates during document modifications, reducing redundant operations and potential errors.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 24, 2025

Walkthrough

The update modifies the updateDocument method signatures across multiple database adapter classes, introducing a new boolean parameter to control whether permission updates should be skipped. Logic is added to conditionally bypass permission updates if document permissions remain unchanged, affecting both direct document updates and batch upsert operations. The Document constructor was also adjusted to avoid references in its iteration.

Changes

File(s) Change Summary
src/Database/Adapter.php Added $skipPermissions parameter to abstract updateDocument method signature and docblock.
src/Database/Adapter/MariaDB.php
src/Database/Adapter/Postgres.php
src/Database/Adapter/SQLite.php
Updated updateDocument method to accept $skipPermissions and conditionally execute permission update logic.
src/Database/Adapter/Pool.php Updated updateDocument method signature to include $skipPermissions and delegate accordingly.
src/Database/Database.php Added logic to detect unchanged permissions and pass $skipPermissionsUpdate to adapter methods in update/upsert.
src/Database/Document.php Removed reference in foreach loop in constructor, iterating by value and reassigning processed elements.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Database
    participant Adapter

    Client->>Database: updateDocument(collection, id, document)
    Database->>Database: Compare old and new permissions
    Database->>Adapter: updateDocument(collection, id, document, skipPermissions)
    Adapter-->>Database: Updated Document
    Database-->>Client: Updated Document
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15–20 minutes

Possibly related PRs

Suggested reviewers

  • abnegate

Poem

In the warren where code bunnies dwell,
We hopped through permissions, skipping as well.
With a flag set to true,
No more checks to do,
Our updates are swift—oh, what a tale to tell!
🐇✨


📜 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 15d9559 and b9ee1a7.

📒 Files selected for processing (4)
  • src/Database/Adapter/MariaDB.php (2 hunks)
  • src/Database/Adapter/Postgres.php (2 hunks)
  • src/Database/Database.php (4 hunks)
  • src/Database/Document.php (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/Database/Document.php
  • src/Database/Database.php
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/Database/Adapter/Postgres.php (6)
src/Database/Adapter/SQLite.php (2)
  • updateDocument (640-847)
  • getSQLTable (1065-1068)
src/Database/Adapter.php (4)
  • updateDocument (704-704)
  • getTenantQuery (1211-1211)
  • trigger (429-439)
  • execute (1217-1217)
src/Database/Adapter/Pool.php (4)
  • updateDocument (238-241)
  • getTenantQuery (488-491)
  • trigger (93-96)
  • execute (493-496)
src/Database/Database.php (3)
  • updateDocument (4097-4293)
  • trigger (580-598)
  • Database (36-6842)
src/Database/Document.php (3)
  • Document (12-462)
  • getId (61-64)
  • getPermissionsByType (137-149)
src/Database/Adapter/SQL.php (4)
  • getSQLTable (1562-1565)
  • getTenantQuery (1682-1714)
  • getPDO (1571-1574)
  • execute (1785-1788)
🪛 PHPMD (2.15.0)
src/Database/Adapter/MariaDB.php

935-935: Avoid unused parameters such as '$id'. (Unused Code Rules)

(UnusedFormalParameter)


1052-1052: Avoid unused local variables such as '$_'. (Unused Code Rules)

(UnusedLocalVariable)

src/Database/Adapter/Postgres.php

1055-1055: Avoid unused parameters such as '$id'. (Unused Code Rules)

(UnusedFormalParameter)


1171-1171: Avoid unused local variables such as '$_'. (Unused Code Rules)

(UnusedLocalVariable)

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

928-935: LGTM: Method signature updated correctly.

The addition of the $skipPermissions boolean parameter is well-implemented with proper typing and descriptive naming. The parameter placement at the end maintains consistency with the pattern used across other adapters.

Note: The static analysis hint about unused $id parameter appears to be a false positive, as the parameter is used throughout the method (e.g., lines 960, 1033, 1081, 1118).


946-1093: Excellent implementation of conditional permissions update.

The permissions update logic is properly encapsulated within the !$skipPermissions conditional, ensuring:

  • Complete bypass of permission operations when $skipPermissions is true
  • Proper variable scoping with permission-related variables only defined when needed
  • Preservation of the original permission update flow when not skipped
  • Clean separation between document attribute updates and permission updates

The implementation correctly addresses the PR objective while maintaining the existing functionality when permissions updates are required.


1052-1052: Static analysis false positive: $_ is intentionally unused.

The $_ variable in the foreach loop is a PHP convention for intentionally unused variables. The code needs the array index $i for parameter binding but doesn't use the permission value itself, making this the correct pattern.

src/Database/Adapter/Postgres.php (3)

1055-1055: Method signature updated correctly.

The addition of the bool $skipPermissions parameter aligns with the abstract method definition and maintains consistency across all database adapters.


1065-1197: Permissions update logic properly optimized.

The conditional execution of permissions updates is correctly implemented. This optimization will skip unnecessary database operations when permissions haven't changed, improving performance while maintaining all existing functionality.


1055-1254: Well-implemented optimization with proper separation of concerns.

The implementation correctly separates permissions updates from document attribute updates. When $skipPermissions is true, only the document attributes are updated while permissions remain untouched, which aligns with the optimization goal of avoiding unnecessary permission operations when they haven't changed.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch skip-permissions

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 generate unit tests to generate unit tests for 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: 0

🔭 Outside diff range comments (1)
src/Database/Adapter/SQLite.php (1)

640-845: Critical: The skipPermissions parameter is not implemented.

The SQLite adapter accepts the $skipPermissions parameter but doesn't use it anywhere in the method implementation. According to the AI summary, other adapters (MariaDB, Postgres) conditionally skip permission updates based on this flag, but SQLite continues to execute all permission operations regardless.

This breaks the intended optimization and creates inconsistent behavior across different database adapters.

The permission update logic (lines 651-843) should be wrapped in a conditional check:

+        if (!$skipPermissions) {
             // All the existing permission logic from lines 651-843
             $sql = "SELECT _type, _permission...";
             // ... rest of permission handling code
+        }

This ensures SQLite behaves consistently with other database adapters when permissions haven't changed.

🧹 Nitpick comments (2)
src/Database/Database.php (2)

4098-4109: Review the permissions comparison logic for potential edge cases

The permissions comparison logic looks generally correct, but there are a few considerations:

  1. The condition $document->offsetExists('$permissions') should probably also check if the old document has permissions to ensure consistent comparison
  2. The sorting approach is good for comparing arrays regardless of order
  3. Consider what happens when one document has permissions and the other doesn't

Consider this more robust approach:

-            if ($document->offsetExists('$permissions')){
+            if ($document->offsetExists('$permissions') && $old->offsetExists('$permissions')){
                 $originalPermissions = $old->getPermissions();
                 $currentPermissions  = $document->getPermissions();

                 sort($originalPermissions);
                 sort($currentPermissions);

                 $skipPermissionsUpdate = ($originalPermissions === $currentPermissions);
+            } elseif (!$document->offsetExists('$permissions') && !$old->offsetExists('$permissions')) {
+                $skipPermissionsUpdate = true; // Both have no permissions, so skip update
+            } else {
+                $skipPermissionsUpdate = false; // One has permissions, other doesn't - update needed
             }

4932-4943: Consistent implementation of permissions comparison logic

The permissions comparison logic in createOrUpdateDocumentsWithIncrease is consistent with the logic in updateDocument. However, it has the same potential edge case issue as mentioned in the previous comment.

Apply the same improvement suggested for the updateDocument method to ensure consistent behavior across both methods.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between d5e57c2 and 647c24c.

📒 Files selected for processing (6)
  • src/Database/Adapter.php (1 hunks)
  • src/Database/Adapter/MariaDB.php (2 hunks)
  • src/Database/Adapter/Pool.php (1 hunks)
  • src/Database/Adapter/Postgres.php (4 hunks)
  • src/Database/Adapter/SQLite.php (1 hunks)
  • src/Database/Database.php (5 hunks)
🧰 Additional context used
🪛 PHPMD (2.15.0)
src/Database/Adapter/SQLite.php

640-640: Avoid unused parameters such as '$skipPermissions'. (Unused Code Rules)

(UnusedFormalParameter)

src/Database/Adapter/Postgres.php

1056-1056: Avoid unused parameters such as '$id'. (Unused Code Rules)

(UnusedFormalParameter)

src/Database/Adapter/MariaDB.php

936-936: Avoid unused parameters such as '$id'. (Unused Code Rules)

(UnusedFormalParameter)


1053-1053: Avoid unused local variables such as '$_'. (Unused Code Rules)

(UnusedLocalVariable)

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

238-241: LGTM! Method signature correctly updated.

The Pool adapter properly extends the updateDocument method signature to include the $skipPermissions parameter. Since this is a proxy class that uses the delegate method with \func_get_args(), the new parameter will be automatically forwarded to the underlying adapter implementation.

src/Database/Adapter.php (1)

700-704: All adapter implementations correctly updated with $skipPermissions.

The abstract updateDocument signature in src/Database/Adapter.php now includes bool $skipPermissions, and all concrete adapter classes implement it:

  • src/Database/Adapter/SQLite.php
  • src/Database/Adapter/Pool.php
  • src/Database/Adapter/Postgres.php
  • src/Database/Adapter/MariaDB.php

No outstanding mismatches found.

src/Database/Adapter/MariaDB.php (2)

929-936: LGTM! Method signature properly updated.

The addition of the $skipPermissions boolean parameter is well-implemented with proper type hinting and documentation.


947-1094: LGTM! Permissions logic correctly wrapped in conditional.

The implementation properly skips all permission-related database operations when $skipPermissions is true while preserving existing functionality. The variable scoping with isset() checks for the prepared statements is handled correctly.

src/Database/Adapter/Postgres.php (4)

1047-1051: LGTM: Documentation formatting improved.

The docblock formatting has been properly cleaned up with consistent spacing.


1056-1056: Method signature correctly updated with new parameter.

The addition of the $skipPermissions boolean parameter aligns with the PR objective. The parameter type and naming are appropriate.

Note: The static analysis warning about unused parameter $id is a false positive - the parameter is actively used throughout the method (lines 1080, 1153, 1187, 1224).


1132-1132: Minor SQL query formatting improvement.

The SQL parameter binding formatting has been slightly improved for better readability.


1066-1198: Conditional Scope Verified: Wraps All Permission Logic Correctly

I’ve confirmed that the if (!$skipPermissions) block opens at line 1066 and its closing brace at line 1196 cleanly encloses every permission‐related operation (reads, diffs, deletes, inserts) and then exits before the attribute‐update section. Braces are properly balanced. No changes needed here.

src/Database/Database.php (4)

593-596: LGTM: Proper initialization of permissions attribute

The code correctly initializes the $permissions attribute to an empty array when it doesn't exist on the document during creation. This ensures consistency and prevents potential null reference issues later in the code.


4266-4266: LGTM: Proper parameter passing to adapter

The $skipPermissionsUpdate flag is correctly passed to the adapter's updateDocument method, maintaining the intended optimization behavior.


4946-4946: Verify the logical condition combination

The condition combines empty($attribute) and $skipPermissionsUpdate with AND logic. This means that when permissions are unchanged AND no specific attribute is being updated, the document update is skipped entirely.

Please verify this logic is correct. The current implementation will skip the document update if:

  1. No specific attribute is being updated (empty($attribute))
  2. Permissions haven't changed ($skipPermissionsUpdate)
  3. Document attributes are the same

This seems correct, but please confirm this is the intended behavior, especially in edge cases where other document metadata might need updating.


5002-5004: LGTM: Proper permissions preservation when skipping update

When permissions update is being skipped, the code correctly preserves the old document's permissions. This ensures that the optimization doesn't inadvertently change permission values.

@fogelito fogelito requested a review from abnegate July 24, 2025 14:15
@abnegate abnegate merged commit bb4f0e4 into main Jul 28, 2025
15 checks passed
@abnegate abnegate deleted the skip-permissions branch July 28, 2025 06:19
This was referenced Aug 4, 2025
@coderabbitai coderabbitai bot mentioned this pull request Aug 19, 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