{{ message }}
Repository navigation
Conversation
CreateFormat added a size to text, which takes none, so TEXT({0}) could
not be used in CREATE TABLE, and gave none to varchar, bpchar, bit,
varbit, the time types and interval, which take one. The hardcoded
"varchar" and "char" cases never matched varchar or bpchar, since they
compared the display name.
Read pg_type.typmodin, which PostgreSQL uses to decide whether a type
takes a modifier, and add the modifier after the type's internal name.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Author
|
I checked the rule against the PostgreSQL-compatible servers I could run. For each, whether CockroachDB under-reports where Spanner over-reports. If losing 🤖 Generated with Claude Code |
This branch has not been deployed
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.

GetSchema("DataTypes")getsCreateFormatandCreateParameterswrong for the character types. A CreateFormat is the "format string that represents how to add this column to a data definition statement, such as CREATE TABLE", but:maintextTEXT({0}),sizetype modifier is not allowed for type "text"character varyingCHARACTER VARYINGcharacterCHARACTERbit,bit varyingBIT,BIT VARYINGtime,timetz,timestamp,timestamptz,intervalTIMESTAMP WITH TIME ZONE(3)would not parse anywayPopulateHardcodedDataTypeInfoswitches onPostgresType.Name, the display name, socase "varchar"never matches (character varying) andcase "char"matches the internal one-byte"char"type (OID 18), notbpchar. Both fall through tocase "text", which is where the size was added, so onlytextand"char"got one.This takes the modifier from the server instead.
pg_type.typmodinis how PostgreSQL itself decides whether a type takes a modifier:texthas none, which is whytext(10)fails.GetDataTypesreads it once (SELECT oid, typmodin::text FROM pg_catalog.pg_type) and adds the modifier after the type's internal name (VARCHAR({0}),BPCHAR({0}),TIMESTAMPTZ({0}),NUMERIC({0},{1})). Parameter names come from thetypmodinfunction, so only the built-in ones are recognised; an extension's modifier is left out, as before. The query is skipped below PostgreSQL 8.3 (wheretypmodinarrived), on Redshift, and when type loading is off, since a failed query would abort the caller's transaction. Because it now queries,GetDataTypesfollows theasyncpath like the other collections.Tests, which fail on
main:DataTypes_CreateFormat_is_accepted_with_its_parameterscreates a column from every row that hasCreateParameters.DataTypes_CreateFormat_has_a_modifier_when_the_type_takes_onepins the expected format per type, including arrays.DataTypes_DataType_matches_the_type_read_for_types_with_a_modifierchecks thatDataTypeis what the reader returns for such a column.All
SchemaTestspass against PostgreSQL 17 (234). The query also runs on CockroachDB (which reports0rather than-for no modifier) and on Spanner through PGAdapter.On Spanner
Selecting from
pg_type.typmodinis the right rule, and Spanner is the problem:typmodinis how PostgreSQL itself decides whether a type takes a modifier.text(10)fails precisely becausetexthas notypmodin, so the rule is accurate by construction.pg_typerows and keepsnumerictypmodin,timestamptztypmodinandintervaltypmodin, then refuses those modifiers ("Type modifier is not supported for type numeric"). A catalog that advertises abilities the server rejects is a catalog bug, and every tool that readspg_typeis misled by it, not just Npgsql.TEXTandNUMERICwrong there today, andtext,char,varcharandbpcharwrong on real PostgreSQL.The internal
"char"type is handled in a separate PR, since itsCreateFormatneeds quoting rather than a modifier.Found with the pengdows ADO.NET conformance suite, whose type-fidelity tests create a column from each
DataTypesrow and round-trip values through it.🤖 Generated with Claude Code