Skip to content

fix(target-postgres): measure identifier length in bytes, not characters - #30127

Open
MahathirMohammadShuvo wants to merge 1 commit into
prisma:mainfrom
MahathirMohammadShuvo:fix/postgres-identifier-byte-limit
Open

fix(target-postgres): measure identifier length in bytes, not characters#30127
MahathirMohammadShuvo wants to merge 1 commit into
prisma:mainfrom
MahathirMohammadShuvo:fix/postgres-identifier-byte-limit

Conversation

@MahathirMohammadShuvo

@MahathirMohammadShuvo MahathirMohammadShuvo commented Aug 25, 2026

Copy link
Copy Markdown

Linked issue

n/a — small change

Summary

quoteIdentifier warned when an identifier exceeded 63 characters, but
PostgreSQL measures NAMEDATALEN - 1 in bytes. A name written in non-ASCII
characters can sit well under 63 characters and still overrun — a 50-character
Cyrillic column name is 96 UTF-8 bytes — so the warning never fired and the
object was silently truncated server-side, leaving the declared name unable to
match the live one.

validateEnumValueLength, in the same module, already measured bytes via
TextEncoder. Both checks now read through one byteLength helper so they
cannot drift apart again, and the warning text says "byte" rather than
"character".

The warn-vs-throw split between the two functions is left alone: it mirrors
PostgreSQL, where an over-long enum label raises invalid enum label but an
over-long identifier is truncated by pg_mbcliplen. The file already documents
that distinction.

Testing performed

  • npx vitest run in packages/3-targets/3-targets/postgres1589 tests,
    92 of 93 files
    . The one failing file, test/migrations/render-typescript.test.ts,
    fails to load on a missing @internal/cli/migration-cli build artifact; it is
    unrelated and fails identically on main.
  • npx vitest run test/sql-utils.test.ts33 passed; with
    src/core/sql-utils.ts reverted to main, 2 failed / 31 passed.
  • biome check on both changed files — exit 0.
  • scripts/lint-deps-focused.mjs on both changed files — no dependency
    violations.
  • The pre-commit and commit-msg hooks both ran and passed.

I did not run pnpm test:packages, test:integration or the e2e suites — this
workspace is only partially built, so those results would not be meaningful.

Skill update

n/a — internal only. The change is a length-check unit and a console.warn
string; no CLI flag, public API, prisma.config.ts field, error code or
glossary term is affected.

Checklist

  • All commits are signed off (git commit -s) per the DCO.
  • I read CONTRIBUTING.md and the change is scoped to one logical concern.
  • Tests are updated.
  • The PR title follows the conventional-commit form that
    skills-contrib/contrib-pr/SKILL.md specifies for outside contributions
    (the TML-NNNN prefix in this checklist is a Linear ticket reference I do
    not have — say the word if you would rather I retitle).
  • The Skill update section above is filled in.

Notes for the reviewer

On duplication. packages/2-sql/1-core/schema-ir/src/naming.ts already has a
byteLength helper with the same shape, and this package does import from that
package's ./naming subpath elsewhere — so consolidating is possible, and it
would need only an export added there. I kept the helper local to stay within
one logical concern, but I am happy to switch to importing it if you would
rather have one copy. That is your call, not mine to make in this PR.

One caveat, pre-existing. TextEncoder measures UTF-8, while PostgreSQL's
limit is bytes in the server encoding. On a non-UTF-8 database the new warning
could fire early. Nothing in packages/3-targets/*/src reads client_encoding,
and naming.ts makes the same UTF-8 assumption, so this is consistent with the
rest of the repo rather than something the change introduces.

Tests. The Cyrillic case is the regression test — it fails on main. The
'€'.repeat(21) case is exactly 63 bytes and passes either way; it is there
because there was no exactly-63 boundary test before, and it is what catches a
>>= slip.

Summary by CodeRabbit

  • Bug Fixes
    • Improved PostgreSQL identifier and enum-value length validation to measure UTF-8 byte length accurately.
    • Warnings now correctly reflect PostgreSQL’s 63-byte identifier limit, including for multibyte characters.
    • Updated validation behavior for values exactly at or exceeding the byte limit.

PostgreSQL truncates identifiers at NAMEDATALEN - 1, which is 63 *bytes*.
quoteIdentifier compared identifier.length, so a name written in non-ASCII
characters could sit well under 63 characters and still overrun: a 50-character
Cyrillic column name is 96 UTF-8 bytes, and the warning never fired.

validateEnumValueLength in the same module already measured bytes via
TextEncoder. Both checks now share one byteLength helper so they cannot drift
apart again, and the warning text says "byte" rather than "character".

Signed-off-by: Mahathir Mohammad Shuvo <shuvo1728@gmail.com>
@MahathirMohammadShuvo
MahathirMohammadShuvo requested a review from a team as a code owner August 25, 2026 14:18
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai

coderabbitai Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro Plus

Run ID: 39303ae3-b8d8-4861-8d26-539bc59aab51

📥 Commits

Reviewing files that changed from the base of the PR and between 7f34164 and c046288.

📒 Files selected for processing (2)
  • packages/3-targets/3-targets/postgres/src/core/sql-utils.ts
  • packages/3-targets/3-targets/postgres/test/sql-utils.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

PostgreSQL length validation now measures UTF-8 bytes through a shared helper. Identifier warnings use the 63-byte limit, enum validation reuses the helper, and tests cover multibyte identifiers above and at the limit.

Changes

PostgreSQL UTF-8 length validation

Layer / File(s) Summary
Shared byte-length validation
packages/3-targets/3-targets/postgres/src/core/sql-utils.ts
Adds a shared UTF-8 byte-length helper. Identifier and enum validation use PostgreSQL’s 63-byte limit.
Multibyte identifier coverage
packages/3-targets/3-targets/postgres/test/sql-utils.test.ts
Updates the warning text assertion and adds tests for identifiers above and exactly at the 63-byte limit.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Merge Risk: ⚪ Minimal · up to c0462

The change corrects identifier-length warnings for multibyte names and adds focused coverage; no actionable merge-blocking risk remains after normal checks and review.

Suggested reviewers: wmadden-electric

🚥 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 and concisely describes the main change: PostgreSQL identifier length validation now measures UTF-8 bytes instead of characters.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 2 files.
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
🧪 Generate unit tests (beta)
  • Create PR with unit 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.

@MahathirMohammadShuvo

Copy link
Copy Markdown
Author

All commits here are signed off per the DCO, as CONTRIBUTING.md requires.

The CLA check may be stale, though. docs/oss/governance.md says:

Prisma Next uses the Developer Certificate of Origin (DCO) 1.1, not a Contributor License Agreement.

and CONTRIBUTING.md says the DCO "is not a Contributor License Agreement and does not transfer copyright". CLAassistant is still enabled on the repo and currently blocks merge, with a Version field on the signing form that appears unconfigured.

Happy to sign whatever is actually required — flagging it in case the integration is a leftover from before the switch to DCO, since it will block every outside contribution the same way.

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.

2 participants