Skip to content

Conversation

@fogelito
Copy link
Contributor

@fogelito fogelito commented Jun 18, 2025

Summary by CodeRabbit

  • New Features

    • Added an option to skip permission checks during document updates for greater update flexibility.
  • Bug Fixes

    • Permission updates are now conditionally executed only when changes occur, improving efficiency.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 18, 2025

"""

Walkthrough

A new boolean parameter $skipPermissions was added to the updateDocument method in the abstract Adapter class and all its concrete implementations. This parameter controls whether permission updates should be skipped during a document update. The main Database class now compares old and new document permissions and passes this flag accordingly to optimize permission synchronization.

Changes

File(s) Change Summary
src/Database/Adapter.php Updated abstract method updateDocument() signature to include $skipPermissions parameter.
src/Database/Adapter/MariaDB.php,
src/Database/Adapter/Postgres.php,
src/Database/Adapter/SQLite.php Updated updateDocument() signature; added conditional permission update logic based on $skipPermissions; improved PHPDoc and exception declarations in SQLite.
src/Database/Adapter/Pool.php Updated updateDocument() signature to include $skipPermissions parameter.
src/Database/Database.php Added logic to compare old and new permissions; passes $skipPermissionsUpdate flag to adapter's updateDocument().

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

Poem

In the warren of code, permissions abound,
But now with a flag, some checks won’t be found.
Skip or enforce, the choice is now clear,
Updates are nimble, the logic sincere.
Hopping through queries, with carrots in sight—
This rabbit approves: the future is bright! 🥕
"""


📜 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 cadce6c and 130beb0.

📒 Files selected for processing (1)
  • src/Database/Adapter/SQLite.php (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Database/Adapter/SQLite.php
⏰ Context from checks skipped due to timeout of 90000ms (12)
  • GitHub Check: Adapter Tests (SharedTables/SQLite)
  • GitHub Check: Adapter Tests (SQLite)
  • GitHub Check: Adapter Tests (SharedTables/MariaDB)
  • GitHub Check: Adapter Tests (SharedTables/Postgres)
  • GitHub Check: Adapter Tests (Pool)
  • GitHub Check: Adapter Tests (SharedTables/MySQL)
  • GitHub Check: Adapter Tests (MySQL)
  • GitHub Check: Adapter Tests (Postgres)
  • GitHub Check: Adapter Tests (Mirror)
  • GitHub Check: Adapter Tests (MariaDB)
  • GitHub Check: Unit Test
  • GitHub Check: CodeQL
✨ 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: 4

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

630-643: $skipPermissions parameter is ignored – expensive permission queries still execute

The new boolean parameter is accepted but never referenced.
As a result, the adapter always performs:

  • A full read of the _perms table (SELECT)
  • Diff calculation + dynamic DELETE / INSERT statements

This defeats the purpose of the “Skip permissions update” feature and keeps the old performance profile.

A minimal fix is to wrap the whole permissions-handling block (SELECT on line 651 through construction of $stmtAddPermissions on line 781) in a guard:

+        $name = $this->filter($collection);

+        // Short-circuit when permission updates are not required
+        if ($skipPermissions) {
+            $stmtRemovePermissions = null;
+            $stmtAddPermissions    = null;
+        } else {
             // existing SELECT, diff, DELETE/INSERT logic …
-        $name = $this->filter($collection);
+        }  // end ! $skipPermissions

Failing to implement this guard means callers cannot rely on the new optimisation.
Please adjust before merging.

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

1244-1251: Atomicity: attributes and permissions are updated in separate statements

$stmt, $stmtRemovePermissions, and $stmtAddPermissions execute independently; a failure in the later statements leaves the document half-updated.

Wrap the three statements in a transaction (or reuse an existing one) so the whole update rolls back on error, e.g.:

$this->startTransaction();
try {
    $this->execute($stmt);
    if (isset($stmtRemovePermissions)) { $this->execute($stmtRemovePermissions); }
    if (isset($stmtAddPermissions))    { $this->execute($stmtAddPermissions); }
    $this->commit();
} catch (Throwable $e) {
    $this->rollback();
    throw $e;
}

(or delegate to the higher-level caller if a transaction is already open).

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

630-636: Docblock advertises DuplicateException but method throws Duplicate

@throws DuplicateException was added, yet the catch still instantiates new Duplicate(...) (line 835).
Either:

  1. Change the caught/ re-thrown exception to DuplicateException, or
  2. Revert the docblock to @throws Duplicate.

Keeping them inconsistent will mislead static analysers and developers.

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

948-1047: Large inline SQL string concatenation needs indentation + braces fix

Several multiline strings inside the new permission-sync block are indented with tabs/spaces that do not match PSR-12, and some if / foreach braces are mis-aligned – the linter reports braces_position / statement_indentation.

Run php-cs-fixer (or the project’s configured CS tool) on this method to avoid CI failures.

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

1080-1101: Use associative fetch to avoid numeric duplicates

$permissionsStmt->fetchAll() defaults to PDO::FETCH_BOTH, producing both numeric and associative keys, doubling memory and risking typos. Fetch only associative rows:

-$permissions = $permissionsStmt->fetchAll();
+$permissions = $permissionsStmt->fetchAll(PDO::FETCH_ASSOC);

Keeps the subsequent '_type' / '_permission' access explicit and lean.


1127-1166: SQL placeholder names rely on original array indexes

Placeholders like :_remove_{$type}_{$i} use the original index from array_diff.
If the source permission array has sparse keys, placeholders become e.g. :_remove_read_5, leaving 0-4 unused and complicating debugging.

Consider re-indexing for predictable sequential keys:

-foreach ($permissions as $i => $permission) {
+foreach (array_values($permissions) as $i => $permission) {

Repeat for the addition loop.

📜 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 454b974.

📒 Files selected for processing (5)
  • src/Database/Adapter.php (3 hunks)
  • src/Database/Adapter/MariaDB.php (2 hunks)
  • src/Database/Adapter/Postgres.php (2 hunks)
  • src/Database/Adapter/SQLite.php (1 hunks)
  • src/Database/Database.php (2 hunks)
🧰 Additional context used
🪛 GitHub Actions: Linter
src/Database/Adapter/MariaDB.php

[error] 1-1: PSR 12 linting failed: braces_position and statement_indentation style issues.

src/Database/Adapter/Postgres.php

[error] 1-1: PSR 12 linting failed: braces_position style issue.

src/Database/Database.php

[error] 1-1: PSR 12 linting failed: single_space_around_construct and braces_position style issues.

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Setup & Build Docker Image
  • GitHub Check: CodeQL
🔇 Additional comments (7)
src/Database/Database.php (1)

4286-4286: Propagate new $skipPermissionsUpdate flag safely

The extra boolean argument is now forwarded to Adapter::updateDocument(). Double-check that all adapter implementations declare the new parameter with a default (false) to avoid fatal errors when called from older code paths.

src/Database/Adapter.php (2)

24-24: Skip-permissions flag added but never read in the base class

The property is written (setSkipPermissions) but there is no corresponding getSkipPermissions() or any reference to the field elsewhere in this abstract class.
If the flag is meant to be consumed only by concrete adapters, consider:
• documenting that intent, or
• promoting the method to protected and dropping the public field entirely to avoid leaking an API that does nothing here.


715-718: Signature change may be a breaking API – double-check downstream

updateDocument(..., bool $skipPermissions) is now mandatory.
Confirm that every call-site (and every concrete adapter) was updated; otherwise you’ll get fatal errors.

If painless migration is preferred, consider giving the parameter a default:

-abstract public function updateDocument(string $collection, string $id, Document $document, bool $skipPermissions): Document;
+abstract public function updateDocument(
+    string $collection,
+    string $id,
+    Document $document,
+    bool $skipPermissions = false
+): Document;
src/Database/Adapter/MariaDB.php (2)

930-938: Method signature aligned – good catch

The adapter now implements the new $skipPermissions parameter.
No issues spotted with the declaration itself.


1051-1081: Parameter placeholders reused – risk of collision

:_uid and :_tenant placeholders are bound once, then reused across multiple VALUES rows.
That’s legal for PDO but each VALUES tuple already contains constant :_uid / :_tenant, so only one value is actually transmitted per execute.
If rows may differ (batch updates) you need unique placeholders per tuple.

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

1048-1058: Backward-compatibility break: new non-optional parameter without default

updateDocument() now requires bool $skipPermissions, turning a previously 3-arg call into 4-args.
Any caller that wasn’t updated will now fatal-error.
If you intend optional behaviour, add a default:

-public function updateDocument(string $collection, string $id, Document $document, bool $skipPermissions): Document
+public function updateDocument(
+    string   $collection,
+    string   $id,
+    Document $document,
+    bool     $skipPermissions = false
+): Document

Otherwise, please confirm that every invocation site (including userland code extending the adapter) has been migrated.


1067-1074: Style: PSR-12 brace spacing triggers linter failure

The CI reports “braces_position style issue”.
Root cause is the missing space before the opening brace:

if (!$skipPermissions){

Apply the canonical spacing:

-if (!$skipPermissions){
+if (! $skipPermissions) {

(Repeat for the closing ) / { pattern elsewhere if copy-pasted.)
[ suggest_nitpick ]

@fogelito fogelito requested a review from abnegate June 18, 2025 14:53
fogelito and others added 2 commits June 19, 2025 09:21
Co-authored-by: Jake Barnby <jakeb994@gmail.com>
@fogelito fogelito requested a review from abnegate June 19, 2025 06:28
@utopia-php utopia-php deleted a comment from coderabbitai bot Jun 19, 2025
@abnegate abnegate merged commit a1be186 into main Jul 21, 2025
15 checks passed
@abnegate abnegate deleted the optimize-update-document branch July 21, 2025 05:14
@coderabbitai coderabbitai bot mentioned this pull request Jul 22, 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