Skip to content

sql/types: reintroduce downgradeType for NAME compatibility in mixed clusters#154363

Merged
craig[bot] merged 1 commit intocockroachdb:masterfrom
spilchen:gh-153322/250929/0829/support-name-mixed/pr-ready
Sep 29, 2025
Merged

sql/types: reintroduce downgradeType for NAME compatibility in mixed clusters#154363
craig[bot] merged 1 commit intocockroachdb:masterfrom
spilchen:gh-153322/250929/0829/support-name-mixed/pr-ready

Conversation

@spilchen
Copy link
Copy Markdown
Contributor

This patch restores the downgradeType hook to maintain serialization compatibility for the NAME type in mixed-version clusters (v25.3 and 25.4).

In previous releases, a NAME type could be misinterpreted by older nodes. Specifically, a v25.3 node deserializing a NAME encoded by a v25.4 node would mistakenly treat it as text (oid.T_text). This was due to the old upgradeType logic overwriting the OID when no VisibleType was set, causing T_name to degrade to T_text. PR #148694 addressed this issue for v25.4 by changing upgradeType (to avoid clobbering a provided OID) and removing the downgradeType function.

However, the follow-up fix for mixed-version serialization (PR #152633) relied on the InternalType.VisibleType field to tag string types for older nodes. Because the NAME type doesn’t use a VisibleType (it’s represented as a STRING family with a special OID), that change didn’t cover NAME. As a result, NAME remained broken in a 25.3/25.4 mixed cluster.

This commit explicitly handles NAME during serialization. When sending a NAME type to the wire, we downgrade it to the legacy encoding: we set its type family to Family=name (legacy enum value 11) so that v25.3 nodes recognize it as a NAME. Additionally, if the locale is an empty string, we set it to nil to ensure older versions don’t misclassify the NAME as a collated string. Together, these steps preserve the correct type interpretation on older nodes.

Once all nodes are on v25.4, this compatibility shim can be removed. At that point, the improved upgrade logic in v25.4 (which no longer overrides a valid OID) means we won’t need to downgrade types for backward compatibility. We may also perform a one time descriptor migration to update any NAME descriptors to the modern format after the cluster upgrade. In short, downgradeType for NAME is a temporary measure to bridge the v25.3 gap.

Fixes #153322

Release note: None

@spilchen spilchen self-assigned this Sep 29, 2025
@cockroach-teamcity
Copy link
Copy Markdown
Member

This change is Reviewable

@spilchen spilchen force-pushed the gh-153322/250929/0829/support-name-mixed/pr-ready branch from 3e49b9c to 47a0640 Compare September 29, 2025 14:30
Copy link
Copy Markdown
Collaborator

@rafiss rafiss left a comment

Choose a reason for hiding this comment

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

nice find! just had one question about skipping the downgradeType logic conditionally

return t.InternalType.Size()
// Need to first downgrade the type before delegating to InternalType,
// because Marshal will downgrade.
temp := *t
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

this line with the pointer dereference was actually the original cause of the race condition. could we add an early-exit so we don't do anything for all types that do not have oid == T_name?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good idea. I applied this comment.

return protoutil.Marshal(&t.InternalType)
// First downgrade to a struct that will be serialized in a backwards-
// compatible bytes format.
temp := *t
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

similar to above -- we can skip this pointer dereference if the oid is not T_name

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done.

@rafiss rafiss added the backport-25.4.x Flags PRs that need to be backported to 25.4 label Sep 29, 2025
…clusters

This patch restores the `downgradeType` hook to maintain serialization
compatibility for the NAME type in mixed-version clusters (v25.3 and 25.4).

In previous releases, a NAME type could be misinterpreted by older nodes.
Specifically, a v25.3 node deserializing a NAME encoded by a v25.4 node would
mistakenly treat it as text (`oid.T_text`). This was due to the old
`upgradeType` logic overwriting the OID when no `VisibleType` was set, causing
`T_name` to degrade to `T_text`. PR cockroachdb#148694 addressed this issue for v25.4 by
changing `upgradeType` (to avoid clobbering a provided OID) and removing the
`downgradeType` function.

However, the follow-up fix for mixed-version serialization (PR cockroachdb#152633) relied
on the `InternalType.VisibleType` field to tag string types for older nodes.
Because the NAME type doesn’t use a `VisibleType` (it’s represented as a
STRING family with a special OID), that change didn’t cover NAME. As a
result, NAME remained broken in a 25.3/25.4 mixed cluster.

This commit explicitly handles NAME during serialization. When sending a NAME
type to the wire, we downgrade it to the legacy encoding: we set its type
family to `Family=name` (legacy enum value 11) so that v25.3 nodes recognize
it as a NAME. Additionally, if the locale is an empty string, we set it to
`nil` to ensure older versions don’t misclassify the NAME as a collated
string. Together, these steps preserve the correct type interpretation
on older nodes.

Once all nodes are on v25.4, this compatibility shim can be removed. At that
point, the improved upgrade logic in v25.4 (which no longer overrides a valid
OID) means we won’t need to downgrade types for backward compatibility. We may
also perform a one time descriptor migration to update any NAME descriptors to
the modern format after the cluster upgrade. In short, `downgradeType` for NAME
is a temporary measure to bridge the v25.3 gap.

Fixes cockroachdb#153322

Release note: None
@spilchen spilchen force-pushed the gh-153322/250929/0829/support-name-mixed/pr-ready branch from 47a0640 to 036b796 Compare September 29, 2025 17:23
@spilchen spilchen marked this pull request as ready for review September 29, 2025 17:24
@spilchen spilchen requested a review from a team September 29, 2025 17:24
Copy link
Copy Markdown
Contributor Author

@spilchen spilchen left a comment

Choose a reason for hiding this comment

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

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @rafiss)

return t.InternalType.Size()
// Need to first downgrade the type before delegating to InternalType,
// because Marshal will downgrade.
temp := *t
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good idea. I applied this comment.

return protoutil.Marshal(&t.InternalType)
// First downgrade to a struct that will be serialized in a backwards-
// compatible bytes format.
temp := *t
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done.

@spilchen
Copy link
Copy Markdown
Contributor Author

TFTR!

bors r+

@craig
Copy link
Copy Markdown
Contributor

craig bot commented Sep 29, 2025

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-25.4.x Flags PRs that need to be backported to 25.4 v26.1.0-prerelease

Projects

None yet

Development

Successfully merging this pull request may close these issues.

roachtest: schemachange/mixed-versions failed [function doesn't exist]

3 participants