=== Applying patches on top of PostgreSQL commit ID 57926d757ab43852021d917b6221687a341c8385 === /etc/rc.d/jail: WARNING: Per-jail configuration via jail_* variables is obsolete. Please consider migrating to /etc/jail.conf. Fri Oct 16 12:03:30 UTC 2026 On branch cf/7449 nothing to commit, working tree clean === using 'git am' to apply patch ./v2-0001-Fix-jsonb_object_agg-used-as-a-window-function.patch === Applying: Fix jsonb_object_agg() used as a window function. Using index info to reconstruct a base tree... M src/backend/utils/adt/jsonb.c M src/backend/utils/adt/jsonb_util.c Falling back to patching base and 3-way merge... Auto-merging src/backend/utils/adt/jsonb_util.c CONFLICT (content): Merge conflict in src/backend/utils/adt/jsonb_util.c Auto-merging src/backend/utils/adt/jsonb.c CONFLICT (content): Merge conflict in src/backend/utils/adt/jsonb.c error: Failed to merge in the changes. hint: Use 'git am --show-current-patch=diff' to see the failed patch Patch failed at 0001 Fix jsonb_object_agg() used as a window function. When you have resolved this problem, run "git am --continue". If you prefer to skip this patch, run "git am --skip" instead. To restore the original branch and stop patching, run "git am --abort". === using patch(1) to apply patch ./v2-0001-Fix-jsonb_object_agg-used-as-a-window-function.patch === patching file src/backend/utils/adt/jsonb.c Hunk #1 FAILED at 1725. 1 out of 1 hunk FAILED -- saving rejects to file src/backend/utils/adt/jsonb.c.rej patching file src/backend/utils/adt/jsonb_util.c Hunk #1 FAILED at 2103. 1 out of 1 hunk FAILED -- saving rejects to file src/backend/utils/adt/jsonb_util.c.rej Removing src/backend/utils/adt/jsonb.c.rej Removing src/backend/utils/adt/jsonb_util.c.rej === using 'git apply' to apply patch ./v2-0001-Fix-jsonb_object_agg-used-as-a-window-function.patch === Applied patch to 'src/backend/utils/adt/jsonb.c' with conflicts. Applied patch to 'src/backend/utils/adt/jsonb_util.c' with conflicts. U src/backend/utils/adt/jsonb.c U src/backend/utils/adt/jsonb_util.c diff --cc src/backend/utils/adt/jsonb.c index 29efd5885ea,804bdbc93ce..00000000000 --- a/src/backend/utils/adt/jsonb.c +++ b/src/backend/utils/adt/jsonb.c @@@ -1727,28 -1726,29 +1727,51 @@@ jsonb_object_agg_finalfn(PG_FUNCTION_AR * Note that this will run uniqueifyJsonbObject each time; that's hard to * avoid, since duplicate pairs may have been added since the previous * finalization. uniqueifyJsonbObject can be applied repeatedly (with the ++<<<<<<< ours + * same unique_keys/skip_nulls options) without breaking the data + * structure invariants, except that it removes null values if told to. + * That's problematic when unique_keys is also set, since that might + * prevent detection of a later-added key that duplicates an existing one + * with null value. Therefore, when both options are set, make a copy of + * the pairs array and uniqueify that, keeping the original unmodified. ++======= + * same unique_keys/skip_nulls options) without damaging the data + * structure, except that it removes null values. That is harmless unless + * unique_keys is also set, since nulls are skipped before duplicates are + * looked for. But the unique check must still see them, so in that case + * run it on a copy of the pairs. ++>>>>>>> theirs */ result = arg->pstate; + if (result.parseState->unique_keys && result.parseState->skip_nulls) + { + JsonbParseState *oldps = result.parseState; + int npairs = oldps->contVal.val.object.nPairs; + + Assert(oldps->next == NULL); + copyps = *oldps; + copyps.contVal.val.object.pairs = palloc_array(JsonbPair, npairs); + memcpy(copyps.contVal.val.object.pairs, + oldps->contVal.val.object.pairs, + npairs * sizeof(JsonbPair)); + result.parseState = ©ps; + } + if (result.parseState->unique_keys && result.parseState->skip_nulls) + { + JsonbParseState *ps = result.parseState; + int npairs = ps->contVal.val.object.nPairs; + + Assert(ps->next == NULL); + result.parseState = palloc_object(JsonbParseState); + *result.parseState = *ps; + result.parseState->contVal.val.object.pairs = + palloc_array(JsonbPair, npairs); + memcpy(result.parseState->contVal.val.object.pairs, + ps->contVal.val.object.pairs, + npairs * sizeof(JsonbPair)); + } + pushJsonbValue(&result, WJB_END_OBJECT, NULL); /* We expect result.parseState == NULL after closing the object */ diff --cc src/backend/utils/adt/jsonb_util.c index 574bd1a307f,83959dcc197..00000000000 --- a/src/backend/utils/adt/jsonb_util.c +++ b/src/backend/utils/adt/jsonb_util.c @@@ -2104,9 -2105,8 +2104,14 @@@ uniqueifyJsonbObject(JsonbValue *object pairs[nNewPairs] = *ptr; /* ++<<<<<<< ours + * Renumber so that order fields again match pairs' array indexes. + * This ensures that if any more pairs are added later, they will + * correctly be seen as later than these. ++======= + * Renumber so the orders stay below nPairs. Pairs appended later + * must still win if we are called again. ++>>>>>>> theirs */ pairs[nNewPairs].order = nNewPairs; nNewPairs++;