Skip to content

Fix Rails 7.2 JSONB pluck type casting#1209

Open
rajaravivarma-r wants to merge 1 commit intojruby:72-stablefrom
rajaravivarma-r:72-jsonb-regression-bug-fix
Open

Fix Rails 7.2 JSONB pluck type casting#1209
rajaravivarma-r wants to merge 1 commit intojruby:72-stablefrom
rajaravivarma-r:72-jsonb-regression-bug-fix

Conversation

@rajaravivarma-r
Copy link
Copy Markdown

@rajaravivarma-r rajaravivarma-r commented Apr 16, 2026

Rails 7.2 started reading AR::Result column types by index during pluck, but PostgreSQLResult only stored types by column name. As a result, JSONB expressions like payload -> 'fields' exposed a named type while column_types[0] stayed nil, and pluck returned raw strings instead of cast JSON values.

Store PostgreSQL result types under both the column name and zero-based column index, and add regression coverage for JSONB array/object/scalar extraction across multiple rows in types_test.

Behaviour examples

This change restores the behaviour we had in earlier Rails / ActiveRecord-JDBC versions, where pluck on JSONB SQL fragments returned type-cast Ruby values instead of raw JSON strings.

Example 1: JSONB array extraction

PostgresqlJsonb.pluck(Arel.sql("payload -> 'fields'"))

Expected behaviour in previous Rails / AR-JDBC versions, and with this change:

[
  [{ "id" => "fld1", "name" => "Name", "type" => "singleLineText" }],
  [{ "id" => "fld2", "name" => "Title", "type" => "number" }]
]

Type-wise, that is:

PostgresqlJsonb.pluck(Arel.sql("payload -> 'fields'")).map(&:class)
# => [Array, Array]

Behaviour seen on Rails 7.2 before this fix:

PostgresqlJsonb.pluck(Arel.sql("payload -> 'fields'")).map(&:class)
# => [String, String]

Example 2: JSONB scalar extraction

PostgresqlJsonb.pluck(Arel.sql("payload -> 'profile' -> 'age'"))

Expected behaviour in previous Rails / AR-JDBC versions, and with this change:

[25, 40]

Type-wise, that is:

PostgresqlJsonb.pluck(Arel.sql("payload -> 'profile' -> 'age'")).map(&:class)
# => [Integer, Integer]

Behaviour seen on Rails 7.2 before this fix:

PostgresqlJsonb.pluck(Arel.sql("payload -> 'profile' -> 'age'"))
# => ["25", "40"]

Internally, the issue was that AR-JDBC exposed the JSONB type under the column name, but Rails 7.2 started reading AR::Result#column_types by column index during pluck. This change stores the type under both the column name and the zero-based column index, so JSONB fragments are cast correctly again.

Rails 7.2 started reading AR::Result column types by index during pluck, but PostgreSQLResult only stored types by column name. As a result, JSONB expressions like payload -> 'fields' exposed a named type while column_types[0] stayed nil, and pluck returned raw strings instead of cast JSON values.

Store PostgreSQL result types under both the column name and zero-based column index, and add regression coverage for JSONB array/object/scalar extraction across multiple rows in types_test.
@rajaravivarma-r
Copy link
Copy Markdown
Author

rajaravivarma-r commented Apr 16, 2026

After upgrading from Rails 7.0 to 7.2 our code started to break because of an incompatibility between Rails 7.2 and activerecord-jdbc-adapter. I investigated the problem with the help of an AI tool and made this PR with its help.

It would be nice if I could get this fixed in a activerecord-jdbc-adapter 72.x version.

Happy to modify this PR as required by the maintainer. TIA.

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.

1 participant