Skip to content

fix(quaint): cast BigInt to text in JSON aggregation#5745

Merged
aqrln merged 2 commits intoprisma:mainfrom
polaz:fix/#1-bigint-json-cast
Jan 20, 2026
Merged

fix(quaint): cast BigInt to text in JSON aggregation#5745
aqrln merged 2 commits intoprisma:mainfrom
polaz:fix/#1-bigint-json-cast

Conversation

@polaz
Copy link
Copy Markdown
Contributor

@polaz polaz commented Jan 20, 2026

Problem

When using relationJoins with BigInt fields in Prisma 7, JavaScript's JSON.parse loses precision for integers larger than Number.MAX_SAFE_INTEGER (2^53 - 1).

This happens because PostgreSQL's JSONB_BUILD_OBJECT returns BigInt values as JSON numbers, which JavaScript cannot represent precisely.

Example:

// Original BigInt ID: 312590077454712834
// After JSON.parse: 312590077454712830 (corrupted!)

Solution

Cast BigInt columns to ::text inside JSONB_BUILD_OBJECT calls, similar to how MONEY is already cast to ::numeric.

-- Before
JSONB_BUILD_OBJECT('id', "id")

-- After  
JSONB_BUILD_OBJECT('id', "id"::text)

This ensures BigInt values are returned as JSON strings, preserving full precision when parsed in JavaScript.

Changes

  • Added BigInt → ::text cast in visit_json_build_obj_expr (quaint/src/visitor/postgres.rs)
  • Added test case for BigInt casting

Related

Test plan

  • Added unit test for BigInt casting in test_json_build_object
  • CI tests pass

Cast BigInt columns to ::text inside JSONB_BUILD_OBJECT to preserve
precision when parsed by JavaScript. JavaScript's JSON.parse loses
precision for integers larger than 2^53-1 (Number.MAX_SAFE_INTEGER).

This is analogous to the existing MONEY -> ::numeric cast.

Closes prisma#1
Copilot AI review requested due to automatic review settings January 20, 2026 13:26
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Jan 20, 2026

CLA assistant check
All committers have signed the CLA.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses a critical precision loss issue when using BigInt fields in PostgreSQL's JSONB_BUILD_OBJECT with Prisma 7's relationJoins. JavaScript's JSON.parse cannot accurately represent integers larger than Number.MAX_SAFE_INTEGER (2^53 - 1), causing data corruption. The fix casts BigInt columns to ::text inside JSONB_BUILD_OBJECT calls, ensuring values are returned as JSON strings to preserve full precision.

Changes:

  • Added BigInt to text casting logic in PostgreSQL visitor's visit_json_build_obj_expr method
  • Added test case to verify BigInt casting behavior in JSONB_BUILD_OBJECT

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread quaint/src/visitor/postgres.rs Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Jan 20, 2026

Merging this PR will not alter performance

✅ 11 untouched benchmarks
⏩ 11 skipped benchmarks1


Comparing polaz:fix/#1-bigint-json-cast (fb70b31) with main (ba38d79)

Open in CodSpeed

Footnotes

  1. 11 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Copy link
Copy Markdown
Member

@aqrln aqrln left a comment

Choose a reason for hiding this comment

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

looks good to me, thank you!

@aqrln aqrln added this to the 7.3.0 milestone Jan 20, 2026
@aqrln aqrln merged commit 9d6ad21 into prisma:main Jan 20, 2026
97 checks passed
@polaz polaz deleted the fix/#1-bigint-json-cast branch January 21, 2026 07:08
Aijeyomah pushed a commit to Aijeyomah/prisma-engines that referenced this pull request Jan 26, 2026
## Problem

When using `relationJoins` with BigInt fields in Prisma 7, JavaScript's
`JSON.parse` loses precision for integers larger than
`Number.MAX_SAFE_INTEGER` (2^53 - 1).

This happens because PostgreSQL's `JSONB_BUILD_OBJECT` returns BigInt
values as JSON numbers, which JavaScript cannot represent precisely.

Example:
```
// Original BigInt ID: 312590077454712834
// After JSON.parse: 312590077454712830 (corrupted!)
```

## Solution

Cast BigInt columns to `::text` inside `JSONB_BUILD_OBJECT` calls,
similar to how MONEY is already cast to `::numeric`.

```sql
-- Before
JSONB_BUILD_OBJECT('id', "id")

-- After  
JSONB_BUILD_OBJECT('id', "id"::text)
```

This ensures BigInt values are returned as JSON strings, preserving full
precision when parsed in JavaScript.

## Changes

- Added BigInt → `::text` cast in `visit_json_build_obj_expr`
(quaint/src/visitor/postgres.rs)
- Added test case for BigInt casting

## Related

- prisma/prisma#29009 (TypeScript-level workaround in prisma fork)

## Test plan

- [x] Added unit test for BigInt casting in `test_json_build_object`
- [ ] CI tests pass

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
jacek-prisma pushed a commit to prisma/prisma that referenced this pull request Feb 25, 2026
)

## Summary

This PR adds a regression test for a critical bug where BigInt values
lose precision when using driver adapters (like `@prisma/adapter-pg`)
with the `relationJoins` preview feature enabled.

Fixes #29010

### The Problem

When `previewFeatures = ["relationJoins"]` is enabled, Prisma uses
lateral joins to fetch related data. The related records are returned as
JSON-aggregated columns. When parsing this JSON data, standard
`JSON.parse()` converts large integers (exceeding
`Number.MAX_SAFE_INTEGER`) to JavaScript Numbers, silently corrupting
the values.

**Example corruption:**
- Original value: `312590077454712834`
- After JSON.parse: `312590077454712800` (precision lost!)

### The Fix

The fix is implemented at the SQL level in `prisma-engines`:
- Postgres: cast BigInt to text in `JSONB_BUILD_OBJECT`
(prisma/prisma-engines#5745)
- MySQL + CockroachDB: cast BigInt/INT8 values to string in JSON
builders (prisma/prisma-engines#5752)

BigInt columns are cast to string before JSON aggregation, so values
arrive as strings and are correctly parsed without precision loss.

**Changes in this PR:**
- Added regression test in
`packages/client/tests/functional/issues/29010-bigint-precision-relation-joins/`
- Minor type safety improvement (explicit `as Value` cast) in
`data-mapper.ts`

## Reproduction

<details>
<summary>Schema</summary>

```prisma
generator client {
  provider        = "prisma-client-js"
  previewFeatures = ["driverAdapters", "relationJoins"]
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model User {
  id    BigInt     @id @default(autoincrement())
  files UserFile[]
}

model UserFile {
  id     String @id @default(uuid())
  userId BigInt
  user   User   @relation(fields: [userId], references: [id])
}
```

</details>

<details>
<summary>Test Code</summary>

```typescript
// Create test data
const user = await prisma.user.create({ data: {} })
const file = await prisma.userFile.create({ data: { userId: user.id } })

// Fetch with include (triggers relationJoins)
const result = await prisma.userFile.findUnique({
  where: { id: file.id },
  include: { user: true }
})

// Before fix: result.userId !== result.user.id (BigInt corrupted in nested relation)
// After fix: result.userId === result.user.id (correct)
```

</details>

## Test Plan

- [x] Regression test added for BigInt precision in relationJoins
queries
- [x] Test covers PostgreSQL, CockroachDB, and MySQL (requires updated
Wasm artifacts from prisma-engines#5752)
- [x] Tests nested relationJoins queries

## Breaking Changes

None. This is a bugfix that preserves intended behavior.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Release Notes

* **Bug Fixes**
* Improved JSON data parsing and type handling in data mapping
operations.

* **Tests**
* Added comprehensive test coverage for BigInt precision with
relationJoins across PostgreSQL, CockroachDB, and MySQL database
providers.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Oleksii Orlenko <alex@aqrln.net>
dimsssss pushed a commit to dimsssss/prisma-engines that referenced this pull request Feb 26, 2026
## Problem

When using `relationJoins` with BigInt fields in Prisma 7, JavaScript's
`JSON.parse` loses precision for integers larger than
`Number.MAX_SAFE_INTEGER` (2^53 - 1).

This happens because PostgreSQL's `JSONB_BUILD_OBJECT` returns BigInt
values as JSON numbers, which JavaScript cannot represent precisely.

Example:
```
// Original BigInt ID: 312590077454712834
// After JSON.parse: 312590077454712830 (corrupted!)
```

## Solution

Cast BigInt columns to `::text` inside `JSONB_BUILD_OBJECT` calls,
similar to how MONEY is already cast to `::numeric`.

```sql
-- Before
JSONB_BUILD_OBJECT('id', "id")

-- After  
JSONB_BUILD_OBJECT('id', "id"::text)
```

This ensures BigInt values are returned as JSON strings, preserving full
precision when parsed in JavaScript.

## Changes

- Added BigInt → `::text` cast in `visit_json_build_obj_expr`
(quaint/src/visitor/postgres.rs)
- Added test case for BigInt casting

## Related

- prisma/prisma#29009 (TypeScript-level workaround in prisma fork)

## Test plan

- [x] Added unit test for BigInt casting in `test_json_build_object`
- [ ] CI tests pass

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
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.

4 participants