Fix JSON null partial updates#3855
Merged
Merged
Conversation
Use jsonb_set_lax for JSONB partial updates when targeting PostgreSQL 16 or later so SQL null values are written as JSON null rather than nulling the whole document. Keep older PostgreSQL versions on jsonb_set/json_set with a JSON null fallback for nullable update values. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR fixes JSON/jsonb partial-update translation for ExecuteUpdate(Async) so that CLR null updates write JSON null instead of accidentally flowing SQL NULL into PostgreSQL JSON update functions (which can null out the entire JSON document). For PostgreSQL 16+ (and non-Redshift), it prefers jsonb_set_lax to rely on its default use_json_null behavior; older/non-lax paths keep using explicit JSON-null fallback behavior.
Changes:
- Update JSON scalar serialization and JSON partial-update setter generation to correctly treat SQL NULL as JSON null and to use
jsonb_set_laxwhen supported. - Add helper logic to detect nullable SQL expressions and apply
COALESCE(..., 'null'::jsonb/json)whenjsonb_set_laxisn’t available. - Update functional test SQL baselines for JSON bulk updates and various JSON type tests to reflect the new SQL shape.
Show a summary per file
| File | Description |
|---|---|
| src/EFCore.PG/Query/Internal/NpgsqlQueryableMethodTranslatingExpressionVisitor.cs | Implements JSON null handling and switches to jsonb_set_lax on PG16+ for nullable JSONB partial updates. |
| test/EFCore.PG.FunctionalTests/Query/Associations/ComplexJson/ComplexJsonBulkUpdateNpgsqlTest.cs | Updates bulk-update SQL baselines to expect jsonb_set_lax where applicable. |
| test/EFCore.PG.FunctionalTests/Types/Temporal/NpgsqlTimeSpanTypeTest.cs | Updates JSON ExecuteUpdate SQL baselines to jsonb_set_lax. |
| test/EFCore.PG.FunctionalTests/Types/Temporal/NpgsqlTimeOnlyTypeTest.cs | Updates JSON ExecuteUpdate SQL baselines to jsonb_set_lax. |
| test/EFCore.PG.FunctionalTests/Types/Temporal/NpgsqlDateTimeUtcTypeTest.cs | Updates JSON ExecuteUpdate SQL baselines to jsonb_set_lax. |
| test/EFCore.PG.FunctionalTests/Types/Temporal/NpgsqlDateTimeUnspecifiedTypeTest.cs | Updates JSON ExecuteUpdate SQL baselines to jsonb_set_lax. |
| test/EFCore.PG.FunctionalTests/Types/Temporal/NpgsqlDateTimeOffsetTypeTest.cs | Updates JSON ExecuteUpdate SQL baselines to jsonb_set_lax. |
| test/EFCore.PG.FunctionalTests/Types/Temporal/NpgsqlDateOnlyTypeTest.cs | Updates JSON ExecuteUpdate SQL baselines to jsonb_set_lax. |
| test/EFCore.PG.FunctionalTests/Types/Numeric/NpgsqlShortTypeTest.cs | Updates JSON ExecuteUpdate SQL baselines to jsonb_set_lax. |
| test/EFCore.PG.FunctionalTests/Types/Numeric/NpgsqlLongTypeTest.cs | Updates JSON ExecuteUpdate SQL baselines to jsonb_set_lax. |
| test/EFCore.PG.FunctionalTests/Types/Numeric/NpgsqlIntTypeTest.cs | Updates JSON ExecuteUpdate SQL baselines to jsonb_set_lax. |
| test/EFCore.PG.FunctionalTests/Types/Numeric/NpgsqlFloatTypeTest.cs | Updates JSON ExecuteUpdate SQL baselines to jsonb_set_lax. |
| test/EFCore.PG.FunctionalTests/Types/Numeric/NpgsqlDoubleTypeTest.cs | Updates JSON ExecuteUpdate SQL baselines to jsonb_set_lax. |
| test/EFCore.PG.FunctionalTests/Types/Numeric/NpgsqlDecimalTypeTest.cs | Updates JSON ExecuteUpdate SQL baselines to jsonb_set_lax. |
| test/EFCore.PG.FunctionalTests/Types/Networking/NpgsqlMacaddrTypeTest.cs | Updates JSON ExecuteUpdate SQL baselines to jsonb_set_lax. |
| test/EFCore.PG.FunctionalTests/Types/Networking/NpgsqlInetTypeTest.cs | Updates JSON ExecuteUpdate SQL baselines to jsonb_set_lax. |
| test/EFCore.PG.FunctionalTests/Types/Miscellaneous/NpgsqlStringTypeTest.cs | Updates JSON ExecuteUpdate SQL baselines to jsonb_set_lax. |
| test/EFCore.PG.FunctionalTests/Types/Miscellaneous/NpgsqlGuidTypeTest.cs | Updates JSON ExecuteUpdate SQL baselines to jsonb_set_lax. |
| test/EFCore.PG.FunctionalTests/Types/Miscellaneous/NpgsqlByteArrayTypeTest.cs | Updates JSON ExecuteUpdate SQL baselines to jsonb_set_lax. |
| test/EFCore.PG.FunctionalTests/Types/Miscellaneous/NpgsqlBoolTypeTest.cs | Updates JSON ExecuteUpdate SQL baselines to jsonb_set_lax. |
Copilot's findings
- Files reviewed: 20/20 changed files
- Comments generated: 1
Keep generated JSON null expressions typed with the JSON type mapping CLR type instead of object, so COALESCE and JSON setter expressions stay well-typed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
roji
added a commit
that referenced
this pull request
Jun 2, 2026
Member
Author
|
Backported to 10.0.3 via 78e671c |
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.
JSON partial updates currently allow SQL NULL values to flow into PostgreSQL JSON update functions, which can produce SQL NULL for the entire JSON document instead of writing JSON null.
This updates JSON partial update translation to use PostgreSQL 16's
jsonb_set_laxfor nullablejsonbupdates, relying on its defaultuse_json_nullbehavior. Older/non-lax paths continue to usejsonb_set/json_setwith explicit JSON-null fallback. SQL baselines were updated for the affected JSON bulk update and type tests.Addresses #3850.
Tests:
dotnet test --no-restore