feat(api): carry type size and modifier in RowDescription#449
Merged
Conversation
`FieldInfo` hardcoded `type_size` and `type_modifier` to `0` when converting into `FieldDescription`, with a TODO to fill them in. For the modifier this is not merely imprecise. `0` is not "unset": PostgreSQL sends `-1` when a type has no modifier, and clients decode a `0` as a real one. For `numeric` that yields a nonsense display scale, so JDBC-based clients render every value with a long tail of spurious zeros — an unconstrained `numeric` holding `1` displays as `1.000...`. Add `type_size` and `type_modifier` to `FieldInfo` as defaulted fields, so `FieldInfo::new` keeps its current signature, with `with_type_size` / `with_type_modifier` builders mirroring the existing `with_format_options`. The modifier defaults to `-1`. Both values now reach `FieldDescription`, and the reverse `FieldDescription -> FieldInfo` conversion carries them back.
Owner
|
@SebastianThiebaud Thank you! Could you fix the rustfmt issue? I will get this merged soon. |
Contributor
Author
Done! |
sunng87
approved these changes
Jul 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Problem
From<&FieldInfo> for FieldDescriptionhardcodes the type size and modifier, with a TODO:For the type modifier this is not just imprecise, it is actively wrong. PostgreSQL sends
-1when a type has no modifier;0is not "unset" but a valid-looking modifier. Clients decode it and derive a display scale from it: pgJDBC computes a numeric's scale as(typmod - 4) & 0xffff, so0yields a nonsense scale.The user-visible symptom: an unconstrained
numericholding1renders in DataGrip (and other JDBC-based clients) asA declared
numeric(18, 4)is affected too: it cannot advertise its real precision and scale, so clients cannot format it correctly or report it throughResultSetMetaData.Since
FieldInfohas no field for either value, a server built on pgwire currently has no way to send a correctRowDescription, even when it knows the right answer.Change
Adds
type_sizeandtype_modifiertoFieldInfoand passes them through toFieldDescription.This is source-compatible. Both are
#[new(value = ...)]defaulted fields, soFieldInfo::newkeeps its current five-argument signature and no existing caller breaks. They are set withwith_type_size/with_type_modifier, mirroring the existingwith_format_optionsbuilder.The one behavior change is deliberate and is the fix itself:
type_modifiernow defaults to-1instead of0, so servers that do not set it emit PostgreSQL's "no modifier" encoding rather than a modifier that decodes to garbage.type_sizekeeps its0default.The reverse
FieldDescription -> FieldInfoconversion carries both values back, so a round trip no longer discards them.Tests
Two unit tests in
src/api/results.rs:-1, and reachesFieldDescriptionas-1numeric(18, 4)modifier and type size reachFieldDescriptionand survive the round trip back into aFieldInfoI verified the change end to end against a real client: with it applied, a server that previously advertised
typmod=0on every column now advertises-1for unconstrained types and the correctly packed((p << 16) | s) + 4for declarednumeric(p, s), and DataGrip renders the values correctly.I was not able to run the full suite locally: the
rusqlitedev-dependency fails to compile on my toolchain (error[E0658]: use of unstable library feature 'cfg_select'), which is unrelated to this change.cargo buildis clean.