Skip to content

Partial update#886

Open
fogelito wants to merge 35 commits into
mainfrom
partial-update
Open

Partial update#886
fogelito wants to merge 35 commits into
mainfrom
partial-update

Conversation

@fogelito

@fogelito fogelito commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • Bug Fixes

    • Prevents accidental overwriting of internal metadata during updates.
    • Honors configuration for preserving or omitting creation timestamps.
    • Reduces inconsistent tenant/version handling to avoid conflicting saves.
  • Improvements

    • Conditional handling of metadata and permissions to avoid unintended changes.
    • Safer merging and stricter validation of persisted vs incoming data for more reliable updates.

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Database::updateDocument sanitizes in-flight updates (removes internals, optional $createdAt, tenant normalization), validates with PartialStructure against persisted document, restores persisted $sequence before adapter call, and merges persisted data with adapter-updated attributes. MariaDB/Postgres/SQLite adapters now conditionally map internal fields, adjust permission id bindings, and trim UPDATE SET/bindings.

Changes

Document update sanitization and adapter metadata updates

Layer / File(s) Summary
Database sanitization, normalization, validation, sequence restore, and merge
src/Database/Database.php
Strip internal fields from incoming documents; optionally remove $createdAt when preserveDates is false; normalize $tenant in shared-tables mode; validate updates with PartialStructure using the persisted $old as currentDocument; restore persisted $sequence onto the in-flight document before calling the adapter; after adapter returns, merge the persisted array with adapter-updated attributes and continue existing casting/cache/post-update logic.
MariaDB conditional metadata copy and permission id binding / UPDATE clause
src/Database/Adapter/MariaDB.php
updateDocument() conditionally copies _updatedAt, _uid, _createdAt, and _permissions only when those offsets exist on the incoming Document; permission read/delete bind :_uid from method $id; inserted permission _uid uses computed newUid (incoming $id if present else method $id); UPDATE SET uses trimmed $columns and the :_newUid binding was removed.
Postgres conditional metadata copy and permission id binding / UPDATE clause
src/Database/Adapter/Postgres.php
updateDocument() conditionally maps _updatedAt, _uid, _createdAt, _permissions only when present on the incoming Document; permission queries/deletes bind :_uid from method $id; inserted permissions compute _uid from incoming $id when present; UPDATE SET no longer appends _uid = :_newUid and :_newUid binding removed.
SQLite conditional metadata copy and permission id binding / UPDATE clause
src/Database/Adapter/SQLite.php
updateDocument() conditionally sets _updatedAt, _uid, _createdAt, _permissions only when the incoming Document exposes them; permission reads/deletes bind :_uid from method $id; inserting permissions computes newUid from incoming $id if present; UPDATE SET stops appending _uid = :_newUid and its binding removed.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • abnegate

Poem

🐰 I nibble keys both old and new,
I drop the dates that shouldn't stew,
Sequence snug where it must stay,
Adapters mind which fields to convey,
The merged doc hops home, all true.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Partial update' is vague and does not clearly convey what specific changes are being made in this pull request. Clarify the title to better describe the main change, such as 'Support conditional metadata updates in document operations' or 'Make metadata updates conditional on document field presence'.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch partial-update

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.

@greptile-apps

greptile-apps Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

  • Adds partial document update handling across the database update path.
  • Updates SQL and memory adapters to write sparse internal fields without overwriting omitted metadata.
  • Preserves immutable document metadata while validating only provided partial-update fields.
  • Adds e2e coverage for sparse updates, UID renames, and permission replacement behavior.

Confidence Score: 5/5

The changes are focused on partial-update handling and metadata preservation, with no outstanding review comments.

The modified adapters, document handling, and e2e coverage align with the described behavior, and no blocking issues were identified.

T-Rex T-Rex Logs

What T-Rex did

  • An execution environment blocker was identified due to missing php, composer, and docker.
  • Static review of all changed files was performed and showed consistent partial-update logic with no contract mismatches.

T-Rex Ran code and verified through T-Rex

Reviews (25): Last reviewed commit: "tests" | Re-trigger Greptile

Comment thread src/Database/Database.php Outdated
Comment thread src/Database/Database.php Outdated
@github-actions

Copy link
Copy Markdown
Contributor

Claude could not apply patches from: healing (merge conflicts with current branch tip). These tasks need manual attention.

…pters

The partial-update change in Database.php only sets internal attributes
(`$createdAt`, `$updatedAt`, `$permissions`, `$id`) on the Document when
the user explicitly provided them. MariaDB's updateDocument was updated
to honor that (offsetExists checks before writing `_createdAt`, `_uid`,
`_permissions`), but SQLite and Postgres still unconditionally wrote
those columns — using `$document->getCreatedAt()`/`getPermissions()`
(returning null/`"[]"`) and `_uid = :_newUid` bound to
`$document->getId()` (empty string for partial updates without `$id`).
SQLite especially blew up because the row's `_uid` got rewritten to an
empty string, so subsequent `getDocument` calls returned null and any
operator-driven update appeared to lose its result.

Also makes `_updatedAt` conditional in MariaDB so partial updates with
`shouldUpdate=false` (e.g. relationship-only updates) don't overwrite
the parent row's `_updatedAt` with NULL.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Claude pushed fixes from: healing

e29ee24...f94cc01

@github-actions

Copy link
Copy Markdown
Contributor

Claude could not apply patches from: healing (merge conflicts with current branch tip). These tasks need manual attention.

Comment thread src/Database/Adapter/MariaDB.php
@github-actions

Copy link
Copy Markdown
Contributor

Claude could not apply patches from: healing (merge conflicts with current branch tip). These tasks need manual attention.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/Database/Adapter/MariaDB.php (1)

980-991: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Root cause: Conditional internal metadata mapping can leave SET clause empty.

Both adapters now conditionally add _updatedAt, _uid, _createdAt, and _permissions only when the corresponding offsets exist. When the Database layer performs a permissions-only update ($shouldUpdate=false), none of these offsets may be present, and if no user attributes exist, the SET clause becomes empty.

Consider coordinating the fix across both adapters or addressing this at the Database layer by ensuring at least one column is always present when calling the adapter.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Database/Adapter/MariaDB.php` around lines 980 - 991, The adapter builds
$attributes conditionally from $document->offsetExists checks which can produce
an empty SET clause for permissions-only updates; update
src/Database/Adapter/MariaDB.php so the update builder always supplies at least
one column when composing $attributes — for example, ensure '_updatedAt' is
always added (use $document->getUpdatedAt() if available or a fallback like
current timestamp) or add a dedicated internal no-op field key (e.g.,
'_internal_update_flag') when none of
'_updatedAt','_uid','_createdAt','_permissions' were added; keep the checks for
existing offsets but guarantee $attributes is non-empty before building the SET,
and mirror the same change in the other adapter to keep behavior consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/Database/Adapter/MariaDB.php`:
- Around line 980-991: The adapter builds $attributes conditionally from
$document->offsetExists checks which can produce an empty SET clause for
permissions-only updates; update src/Database/Adapter/MariaDB.php so the update
builder always supplies at least one column when composing $attributes — for
example, ensure '_updatedAt' is always added (use $document->getUpdatedAt() if
available or a fallback like current timestamp) or add a dedicated internal
no-op field key (e.g., '_internal_update_flag') when none of
'_updatedAt','_uid','_createdAt','_permissions' were added; keep the checks for
existing offsets but guarantee $attributes is non-empty before building the SET,
and mirror the same change in the other adapter to keep behavior consistent.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0cd5a620-5c8e-445d-bfe2-b0692881fd19

📥 Commits

Reviewing files that changed from the base of the PR and between 6b2a7b5 and f94cc01.

📒 Files selected for processing (4)
  • src/Database/Adapter/MariaDB.php
  • src/Database/Adapter/Postgres.php
  • src/Database/Adapter/SQLite.php
  • src/Database/Database.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Database/Database.php

@github-actions

Copy link
Copy Markdown
Contributor

Claude could not apply patches from: healing (merge conflicts with current branch tip). These tasks need manual attention.

Comment thread src/Database/Database.php Outdated
Comment thread src/Database/Adapter/MariaDB.php
Comment thread src/Database/Adapter/MariaDB.php Outdated
Comment thread tests/e2e/Adapter/Scopes/DocumentTests.php Outdated
Comment thread phpunit.xml
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
stopOnFailure="true"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 stopOnFailure was flipped to true, which halts the entire suite on the first failure. Combined with the always-failing assertion in testPartialUpdateDocument, no tests after that point will execute, hiding the real pass/fail status of the rest of the suite. This should be reverted to false (the project's established default) before merging.

Suggested change
stopOnFailure="true"
stopOnFailure="false"

@utopia-php utopia-php deleted a comment from claude Bot Jun 11, 2026
@utopia-php utopia-php deleted a comment from claude Bot Jun 11, 2026
@utopia-php utopia-php deleted a comment from claude Bot Jun 11, 2026
@utopia-php utopia-php deleted a comment from claude Bot Jun 11, 2026
@utopia-php utopia-php deleted a comment from claude Bot Jun 11, 2026
fogelito added 3 commits June 16, 2026 14:11
…date

# Conflicts:
#	src/Database/Adapter/MariaDB.php
#	src/Database/Adapter/Postgres.php
#	src/Database/Adapter/SQLite.php
#	src/Database/Database.php
Comment thread src/Database/Database.php Outdated
Comment thread tests/e2e/Adapter/Scopes/DocumentTests.php Outdated
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.

1 participant