fix: orderable fractional indexing case-sensitivity issue with PostgreSQL #14867
+235 −23
Add this suggestion to a batch that can be applied as a single commit. This suggestion is invalid because no changes were made to the code. Suggestions cannot be applied while the pull request is closed. Suggestions cannot be applied while viewing a subset of changes. Only one suggestion per line can be applied in a batch. Add this suggestion to a batch that can be applied as a single commit. Applying suggestions on deleted lines is not supported. You must change the existing code in this line in order to create a valid suggestion. Outdated suggestions cannot be applied. This suggestion has been applied or marked resolved. Suggestions cannot be applied from pending reviews. Suggestions cannot be applied on multi-line comments. Suggestions cannot be applied while the pull request is queued to merge. Suggestion cannot be applied right now. Please check back later.
fix: orderable fractional indexing case-sensitivity issue with PostgreSQL
Problem
When using the
orderablefeature with PostgreSQL, reordering documents to the "first" position generates keys that break subsequent reordering operations.Scenario
a0,a1a1beforea0(to make it first)Zzfor the moved documentRoot Cause
The fractional indexing algorithm uses:
A-Zfor "smaller" integer keysa-zfor "larger" integer keysThis relies on ASCII ordering where
'Z'(code 90) <'a'(code 97), soZz < a0.However, PostgreSQL's default collation (
en_US.UTF-8) uses case-insensitive comparison, treating'Z'as'z'. This means:Zz < a0✓Zztreated aszz, sozz > a0✗This mismatch causes:
generateKeyBetweenfunction receives arguments in wrong orderSolution
Modified the fractional indexing algorithm to use only characters that sort consistently across all database collations:
A-Z(uppercase)0-9(digits)a-z(lowercase)a-z(lowercase, unchanged)Key insight: Digits (
0-9) always sort before letters in both ASCII ordering and case-insensitive collations.Before (broken)
After (fixed)
Changes
packages/payload/src/config/orderable/fractional-indexing.jsa-zkeysA-Zkeys are still parsed (for backward compatibility) but won't be generatedBackward Compatibility
a-zcontinue to work correctlyA-Z(uppercase) will be parsed but may sort incorrectly in case-insensitive databases. Users with such keys should run a migration to regenerate them.Testing
Verified the algorithm produces correct ordering:
Related