fix(introspect): decode composite field ordinal as i16 - #5
Merged
Conversation
`pg_attribute.attnum` is a smallint, but `fetch_composite_types` decoded
it as `i32`. sqlx applies no implicit widening, so introspecting any
schema that declares a standalone composite type died with:
ColumnDecode { index: "5", source: "mismatched types; Rust type
`i32` (as SQL type `INT4`) is not compatible with SQL type `INT2`" }
The other ordinal reads in this module go through
`information_schema.columns.ordinal_position`, whose `cardinal_number`
domain really is an int4 — only the pg_catalog query was wrong.
Schemas with no standalone composite type return zero rows and never
decode anything, which is why this stayed hidden.
Also adds the `e2e_postgres` test target that the `test-postgres` CI job
already invokes but which never existed, so the job was silently passing
over nothing. It covers the composite regression plus basic table and
enum introspection.
Fixes #4
LeadcodeDev
force-pushed
the
fix/composite-type-attnum-int2
branch
from
August 1, 2026 14:19
5e8c5f1 to
3dd06ac
Compare
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.
Fixes #4.
The bug
fetch_composite_typesreads the composite field ordinal frompg_attribute.attnum, which is asmallintin the Postgres catalog, but declared the decode target asi32. sqlx applies no implicit widening, so introspection died on the 6th column:Confirmed against Postgres 16:
The other ordinal reads in this module go through
information_schema.columns.ordinal_position, whosecardinal_numberdomain genuinely is anint4— those were always correct. Only thepg_catalogquery was wrong.Why it went unnoticed
The query filters on
t.typtype = 'c'while excluding the implicit row types that back tables. A schema with no standaloneCREATE TYPE ... AS (..)returns zero rows, so nothing is ever decoded and the mismatch stays invisible. It only fires for users who declare real composite types.The fix
Decode as
i16, widen withi32::fromat the assignment. Mirroring the catalog's actual type keeps the divergence frominformation_schemavisible at the call site, which the added comment explains.Tests
CI's
test-postgresjob already runscargo test --all-features --test e2e_postgres -- --include-ignored, buttests/e2e_postgres.rsnever existed — undercontinue-on-error: truethe job has been silently passing over nothing. That gap is what let this ship. This PR adds the file:test_composite_type_is_introspected— the regression; fails onmainwith the exact error above, passes with the fixtest_table_row_type_is_not_a_composite— guards the implicit-row-type exclusiontest_simple_table_generates_struct,test_enum_is_introspected— basic coverage so the target is worth runningEach test works in its own schema so they stay parallel-safe.
Verification
End-to-end against a live Postgres 16 with
CREATE TYPE address AS (street TEXT, city TEXT, zip TEXT), the CLI path from the issue now succeeds:Follow-ups (not in this PR)
chore:commits.continue-on-error: trueon thetest-postgresandtest-mysqljobs still hides real failures.tests/e2e_mysql.rsis referenced by CI too and looks equally absent (unverified).