Skip to content

Fix GEOHASH last character to always output '0' (52-bit precision) - #1635

Merged
Badrish Chandramouli (badrishc) merged 1 commit into
mainfrom
copilot/fix-geohash-last-character
Jul 21, 2026
Merged

Fix GEOHASH last character to always output '0' (52-bit precision)#1635
Badrish Chandramouli (badrishc) merged 1 commit into
mainfrom
copilot/fix-geohash-last-character

Conversation

Copilot AI commented Mar 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes the final character emitted by GEOHASH so it matches the established geohash convention.

A standard geohash is 11 base-32 characters = 55 bits (11 × 5). Garnet stores geo positions as 52-bit values packed into sorted-set scores — 3 bits short of what the 11th character needs. Because those 3 bits are not stored, the 11th character cannot be derived from the score and is emitted as '0' by convention.

Previously GetGeoHashCode shifted the leftover bits into the final 5-bit index, producing a divergent last character. The first 10 characters were already correct; only the 11th changed:

Command Before After
GEOADD k 13.361389 38.115556 PalermoGEOHASH k Palermo sqc8b49rnys sqc8b49rny0

Changes

  • libs/server/Objects/SortedSetGeo/GeoHash.csGetGeoHashCode now sets the last character to '0' and encodes only the first 10 characters from the stored 52 bits.
  • test/standalone/Garnet.test.collections/GeoHashTests.cs and RespSortedSetGeoTests.cs — updated expected GEOHASH outputs to the …0 form.

Notes

  • The decode path is unaffected: coordinates are decoded from the numeric 52-bit score (GetCoordinatesFromLong), never from the 11-character string, so all other GEO* commands retain full available precision.

Fixes #1625

Copilot AI changed the title [WIP] Fix GEOHASH incorrect last character due to truncation handling Fix GEOHASH last character: always output '0' for Redis compatibility Mar 17, 2026
@badrishc
Badrish Chandramouli (badrishc) marked this pull request as ready for review March 17, 2026 20:32
Copilot AI review requested due to automatic review settings March 17, 2026 20:32
@badrishc

Copy link
Copy Markdown
Collaborator

Request your review on this PR, Seth Speaks (@sspeaks) and Paulus Pärssinen (@PaulusParssinen)

Copilot AI 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.

Pull request overview

Updates Garnet’s GEOHASH output to match Redis behavior by forcing the 11th (final) geohash character to '0', since Garnet stores only 52 bits of precision (insufficient for the full 55 bits implied by 11 base32 characters).

Changes:

  • Adjust GeoHash.GetGeoHashCode to force the last base32 character index to 0 (so the last character is always '0').
  • Update geohash expectations in unit/integration tests to reflect the new Redis-compatible output.
  • Change the pinned .NET SDK version in global.json from 10.0.103 to 10.0.102.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
libs/server/Objects/SortedSetGeo/GeoHash.cs Forces the last geohash character to '0' for Redis compatibility under 52-bit precision.
test/Garnet.test/GeoHashTests.cs Updates expected geohash strings and clarifies the '0' last-character convention.
test/Garnet.test/RespSortedSetGeoTests.cs Updates expected GEOHASH output in RESP sorted set geo tests (e.g., Palermo).
global.json Updates the repo’s pinned .NET SDK patch version.

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

Comment thread global.json
Comment thread libs/server/Objects/SortedSetGeo/GeoHash.cs Outdated

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.

Added comment with alternative approach without branches in the inner loop, either will do the job.

All other GEO* functionality will still use the available 52-bit precision that is persisted in the sorted set.

A standard geohash is 11 base-32 characters = 55 bits (11 x 5), but geo
positions are stored as 52-bit values packed into sorted-set scores -- 3 bits
short of what the 11th character needs. Since those bits are not stored, the
11th character cannot be derived and is emitted as '0' by convention.

GetGeoHashCode now sets the last character to '0' and encodes only the first
10 characters from the stored bits. Previously the last character reflected
leftover shifted bits (e.g. "sqc8b49rnys" instead of "sqc8b49rny0"); the
first 10 characters were already correct.

Fixes #1625

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c54c3cfa-79a3-4949-a2ec-ae0658bc7894
@badrishc
Badrish Chandramouli (badrishc) force-pushed the copilot/fix-geohash-last-character branch from 040fc19 to 8b7aff7 Compare July 21, 2026 21:56
@badrishc Badrish Chandramouli (badrishc) changed the title Fix GEOHASH last character: always output '0' for Redis compatibility Fix GEOHASH last character to always output '0' (52-bit precision) Jul 21, 2026
@badrishc

Badrish Chandramouli (badrishc) commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

Rebased onto latest main and polished for merge:

  • Rebased onto current main, resolving the conflict caused by the test move to test/standalone/Garnet.test.collections/. History is now a single clean commit.
  • Both review threads addressed (carried over): the global.json SDK bump was reverted, and GetGeoHashCode uses Paulus Pärssinen (@PaulusParssinen)'s branch-free form (chars[^1] = '0' before the loop, loop over chars.Length - 1).
  • Verified locally: dotnet build (0 warnings), dotnet format --verify-no-changes, and the geo tests (GeoHashTests, CanUseGeoHash, CanUseGeoPos) — all pass.
  • Independent review (self + a separate model pass) confirmed correctness: loop bounds, updated test expectations, edge cases (all-zero, all-ones 0xFFFFFFFFFFFFF), and that the decode path is unaffected (coordinates decode from the numeric 52-bit score, never the string).

@badrishc
Badrish Chandramouli (badrishc) merged commit 52b12af into main Jul 21, 2026
161 checks passed
@badrishc
Badrish Chandramouli (badrishc) deleted the copilot/fix-geohash-last-character branch July 21, 2026 23:51
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.

GEOHASH returns incorrect last character due to missing 52-bit truncation handling

5 participants