Skip to content

fix: Preserve cached String values that look like Int64, UUID or Timestamp - #122

Merged
aashishpatil-g merged 3 commits into
firebase:mainfrom
dmorfav:fix/cache-preserve-string-scalars
Oct 20, 2026
Merged

aashishpatil-g merged 3 commits into
firebase:mainfrom
dmorfav:fix/cache-preserve-string-scalars

Conversation

@dmorfav

@dmorfav dmorfav commented Oct 12, 2026

Copy link
Copy Markdown
Contributor

Fixes firebase/firebase-ios-sdk#16887

On cache hits, AnyCodableValue.init(from:) infers Timestamp → Int64 → UUID for every JSON string, and the lenient parsers accept non-canonical input. Re-encoding then loses the original value: "08001" → "8001", "+5" → "5", an uppercase hex string → lowercase, and a timestamp with an offset → UTC.

Change

  • AnyCodableValue: infer .timestamp / .int64 / .uuid only if re-encoding gives back exactly the original string. Otherwise the value stays .string.
  • CodableTimestamp: move the string formatting into CodableTimestampHelper so that the round-trip check and the encoder use the same code.

Canonical values sent by the server for Int64, UUID and Timestamp fields still infer as before, so AnyValue.decodeValue(Int64.self) and the existing cache behavior stay the same. The cache schema does not change.

Tests

  • AnyValueCodableTests: non-canonical strings keep their exact value, and canonical values are still inferred.
  • CacheTests: a dehydrate/hydrate round trip through SQLiteCacheProvider keeps "08001" and "0012345678".

swift test --filter FirebaseDataConnectUnit passes (83 tests), and so does scripts/style.sh test-only.

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request ensures that string values resembling Int64, UUID, or Timestamp are not incorrectly rewritten in the client cache by verifying that re-encoding reproduces the exact original string. The feedback suggests improving safety by propagating errors instead of using force-try (try!) in the timestamp helper methods, and optimizing the decoding path in AnyCodableValue to avoid expensive exception throwing during type inference.

Comment thread Sources/Internal/CodableTimestamp.swift Outdated
Comment thread Sources/Internal/CodableTimestamp.swift Outdated
Comment thread Sources/Scalars/AnyCodableValue.swift
@aashishpatil-g

Copy link
Copy Markdown
Collaborator

LGTM - thanks for the PR @dmorfav !!

@dmorfav

dmorfav commented Oct 12, 2026

Copy link
Copy Markdown
Contributor Author

LGTM - thanks for the PR @dmorfav !!

Thanks. The workflow runs (check, spm) are waiting for maintainer approval since this is my first contribution from a fork.

@dmorfav

dmorfav commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor Author

@aashishpatil-g here too, the CI failure is unrelated to this change: spm-package-resolved fails resolving firebase-ios-sdk (it requires swift-tools 6.2.1, the runner has 6.1.0). The scheduled spm run on main has been failing the same way since 2026-09-25. Happy to rebase once CI is fixed, or feel free to merge if that check isn't required.

FYI @paulb777

@dmorfav

dmorfav commented Oct 17, 2026

Copy link
Copy Markdown
Contributor Author

I’m keeping an eye on PR #124 so I can update mine once it’s merged.

@ncooke3 ncooke3 closed this Oct 19, 2026
@ncooke3 ncooke3 reopened this Oct 19, 2026
@dmorfav

dmorfav commented Oct 20, 2026

Copy link
Copy Markdown
Contributor Author

hi @aashishpatil-g the PR is green and ready for review.

@aashishpatil-g

Copy link
Copy Markdown
Collaborator

LGTM - merging..

@aashishpatil-g
aashishpatil-g merged commit b873123 into firebase:main Oct 20, 2026
11 checks passed
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.

Client cache rewrites String fields that look like Int64/UUID/Timestamp (e.g. "08001" → "8001")

3 participants