Skip to content

fix(mongo): bump to 1.5.3 so integers past int32 survive a read - #936

Merged
abnegate merged 3 commits into
mainfrom
fix/mongo-int64-regression-tests
Aug 13, 2026
Merged

fix(mongo): bump to 1.5.3 so integers past int32 survive a read#936
abnegate merged 3 commits into
mainfrom
fix/mongo-int64-regression-tests

Conversation

@abnegate

@abnegate abnegate commented Aug 13, 2026

Copy link
Copy Markdown
Member

Closes the utopia-php/database half of appwrite/appwrite#13175BigInt[] Breaks MongoDb.

What was broken

MongoDB\BSON\Document::toPHP() decodes every 64-bit BSON integer as a MongoDB\BSON\Int64 wrapper on all platforms, so anything outside the int32 range came back from Mongo as an object. utopia-php/mongo#49 fixes that at the decode boundary; this bumps the lock to 1.5.3 and adds the two regression tests that hold it in place.

Only utopia-php/mongo moves in the lock, 1.5.2 → 1.5.3.

Why the tests target these two paths

Typed integer/bigint attributes were already fine on main: castingAfter() applies (int)$node, and ext-mongodb 2.x gives Int64 a numeric cast handler, so that returns the right value. The two paths with no cast to lean on were the real leaks:

  1. sum() returns the aggregate total straight off the cursor and declares float|int, so any total past int32 was a hard return type violation:

    TypeError: Utopia\Database\Adapter\Mongo::sum(): Return value must be of type int|float, MongoDB\BSON\Int64 returned
    

    Two rows of 2000000000 is enough to trip it.

  2. Object attributes have no per-key schema, so castingAfter() has nothing to cast against. The wrapper reached the response and serialised as {"count":{"$numberLong":"-3408048000"}} instead of a number — wrong data on the wire, no error anywhere.

Both are in shared scopes rather than MongoDBTest, because the assertion (native PHP integers, no $numberLong in the JSON) is a contract every adapter should meet, not Mongo trivia.

Verification

  • Both tests seen red before the bump, on the exact failures quoted above, and green after.
  • New tests pass on MongoDB, Postgres and Memory; the object one skips on MySQL, MariaDB and SQLite, which have no object support.
  • Full MongoDBTest against the real released 1.5.3: 663 tests, 4997 assertions, 0 failures, 5 pre-existing skips.
  • pint --test passes on both changed files.

Note for anyone reproducing locally: a stale vendor in the test image shows up as two testObjectAttribute*EmptyObject* failures ({} vs []). That is utopia-php/cache 4.0.1 against a lock that wants 4.0.2, not this change. Rebuilding the image clears it.

Not verified

  • Key order in the object test. Asserted with assertEquals plus a $numberLong substring check rather than an exact JSON string, because Postgres jsonb does not preserve key order. So the test pins types and values, not serialised layout.
  • 32-bit PHP. 1.5.3 deliberately keeps the wrapper there, since it is the only lossless representation. Neither repo has a 32-bit CI target, so that branch is reasoned, not exercised.
  • Full e2e for every adapter locally. I ran the two new tests against all six and the complete suite for Mongo only; CI covers the rest.

Summary by CodeRabbit

  • Tests
    • Added coverage for signed 64-bit integers beyond the 32-bit range.
    • Verified large integer values remain native integers across document retrieval, searching, aggregation, caching, and JSON serialization.
    • Confirmed both positive and negative values serialize as standard JSON numbers without numeric wrappers.

Two paths lost or corrupted integer values outside the int32 range on
Mongo, because the driver decodes 64-bit BSON integers as Int64 wrappers
and neither path casts them.

sum() returns the aggregate total straight off the cursor and declares
float|int, so any total past int32 was a return type violation:

  TypeError: Mongo::sum(): Return value must be of type int|float,
  MongoDB\BSON\Int64 returned

Object attributes have no per-key schema, so castingAfter() has nothing
to cast against and the wrapper reached the response, serialising as
{"$numberLong":"-3408048000"} instead of a number.

Both tests live in shared scopes and pass on Mongo, Postgres, MySQL,
MariaDB, SQLite and Memory. They need utopia-php/mongo 1.5.3
(utopia-php/mongo#49), which normalises at the decode boundary.

Refs appwrite/appwrite#13175
1.5.3 normalises BSON int64 to native PHP integers at the decode
boundary (utopia-php/mongo#49), which is what the two tests in the
preceding commit need to pass on Mongo.
@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@abnegate, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 53 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f04cbe02-ca25-4651-a455-8dcf22649c80

📥 Commits

Reviewing files that changed from the base of the PR and between 0b29bf5 and 828daff.

📒 Files selected for processing (1)
  • tests/e2e/Adapter/Scopes/ObjectAttributeTests.php

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 8fd9c06a-2aed-42da-9583-196a6e9d9230

📥 Commits

Reviewing files that changed from the base of the PR and between a8e8386 and 0b29bf5.

⛔ Files ignored due to path filters (1)
  • composer.lock is excluded by !**/*.lock
📒 Files selected for processing (2)
  • tests/e2e/Adapter/Scopes/DocumentTests.php
  • tests/e2e/Adapter/Scopes/ObjectAttributeTests.php

📝 Walkthrough

Walkthrough

The pull request adds end-to-end tests for signed 64-bit integer preservation in documents and object attributes. The tests cover retrieval, queries, aggregation, cache invalidation, native integer types, exact values, and plain JSON serialization.

Changes

64-bit integer preservation

Layer / File(s) Summary
Document integer and aggregation coverage
tests/e2e/Adapter/Scopes/DocumentTests.php
Tests signed 64-bit scalar and array values through document retrieval and queries. The tests also verify plain JSON numbers and an integer sum() result of 4000000000.
Object attribute integer coverage
tests/e2e/Adapter/Scopes/ObjectAttributeTests.php
Tests nested large integers after cache invalidation and retrieval. The tests verify native integer types, exact values, and the absence of $numberLong wrappers.

Estimated code review effort: 2 (Simple) | ~10 minutes

Mergeability Score: ⚪ Minimal · up to 0b29b

This localized dependency update fixes large-integer decoding and adds regression coverage; no actionable merge-blocking risk remains after normal checks and review.

Possibly related PRs

Suggested reviewers: fogelito

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the MongoDB dependency update and its purpose of preserving integers beyond the 32-bit range.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/mongo-int64-regression-tests

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.

@greptile-apps

greptile-apps Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR updates utopia-php/mongo from 1.5.2 to 1.5.3 so decoded 64-bit BSON integers remain native PHP integers on supported 64-bit platforms.

  • Adds regression coverage for large scalar and array integers across document reads, searches, aggregation, and JSON serialization.
  • Adds object-attribute coverage for nested large integers after cache eviction.
  • Updates the locked Mongo dependency source and distribution references.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
composer.lock Updates only utopia-php/mongo from 1.5.2 to 1.5.3, with compatible locked requirements and references.
tests/e2e/Adapter/Scopes/DocumentTests.php Adds cross-adapter regression coverage ensuring large signed integers and aggregate sums retain native integer values.
tests/e2e/Adapter/Scopes/ObjectAttributeTests.php Adds regression coverage ensuring nested large integers in object attributes do not leak BSON numeric wrappers.

Fix All in Greploop

Reviews (2): Last reviewed commit: "fix(test): satisfy level 7 on the json_e..." | Re-trigger Greptile

json_encode() is string|false, which assertStringNotContainsString()
will not take. JSON_THROW_ON_ERROR narrows it to string and turns a
silent false into an exception, which is what we want in a test anyway.
@abnegate
abnegate merged commit 38181c9 into main Aug 13, 2026
22 checks passed
@abnegate
abnegate deleted the fix/mongo-int64-regression-tests branch August 13, 2026 02:26
abnegate added a commit to appwrite/appwrite that referenced this pull request Aug 13, 2026
Carries the int64 regression tests from utopia-php/database#936, and the
unique violation classification work from #733, which now keys off the
violated constraint instead of matching on the driver message.
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