mergedJSONPatch
Introducido en: v26.8.0 Agrega valores JSON fusionándolos con una semántica en la que prevalece la última escritura, e implementa el comportamiento principal de fusión de RFC 7396 JSON Merge Patch a nivel de ruta. La función de agregación almacena el estado como tripletas (key, value, sorting_key), donde cada clave (ruta JSON) solo conserva el registro efectivo más reciente según la sorting_key. Las escrituras de objetos se aplanan en rutas descendientes en el caso de las rutas que el tipoJSON almacena como hojas escalares dinámicas. Las escrituras de ancestros que no son objetos
prevalecen sobre los descendientes en conflicto.
Cada ruta con tipo explícito (declarada con JSON(a Map(...)), JSON(a Tuple(...)),
JSON(a Variant(...)), JSON(a Dynamic), etc.) se trata como un valor atómico: el valor completo de la ruta
se sustituye por el del patch más reciente en lugar de fusionarse en profundidad. Solo las rutas escalares sin tipo (dinámicas) siguen
la semántica de fusión profunda de la RFC 7396.
El sort_key determina qué valor prevalece para cada ruta JSON. Se conserva la fila con el sort_key
más alto. Si dos parches en conflicto tienen la misma clave de ordenación, el resultado depende del orden: prevalece el parche
que se procese en último lugar. No se debe confiar en ORDER BY para deshacer empates de forma determinista.
LIMITACIONES (heredadas de ColumnObject):
-
Eliminación de valores nulos: un patch
{"key": null}no elimina la clave.ColumnObjectdescarta los miembros con valor nulo durante la inserción, por lo que la función no puede distinguir entre “clave ausente” y “clave con valor nulo”. -
Reemplazo con objeto vacío: un patch
{"a": {}}no puede sustituir un valor escalar o array anterior en la rutaa.ColumnObjectdescarta silenciosamente las rutas cuyo valor es un objeto vacío{}, por lo que el patch más reciente no aporta nada y el valor anterior se mantiene. -
Ausencia en rutas tipadas no Nullable: cuando una columna
JSONdeclara una ruta tipada con un tipo no Nullable (p. ej.,JSON(a UInt32)), una fila que omitease almacena con el valor predeterminado del tipo (p. ej.,0). La agregación no puede distinguir entre “ausente” y “escrito explícitamente con el valor predeterminado”, por lo que un patch más reciente que omiteaborra silenciosamente un valor anterior distinto de cero. Para evitarlo, declare las rutas tipadas comoNullable(p. ej.,JSON(a Nullable(UInt32))). Un valor nulo en una ruta tipada Nullable se trata como “ruta ausente” y se omite correctamente. -
Todas las rutas tipadas son atómicas: cada ruta tipada (
Map(K,V),JSON,Dynamic,Tuple(…),Variant(…),Array(…)o cualquier otro tipo declarado) se almacena como un único valor. La agregación reemplaza el valor completo de forma atómica, en lugar de fusionar su contenido en profundidad. Solo las rutas dinámicas (no tipadas, escalares) se fusionan en profundidad, ruta por ruta. -
Ambigüedad por puntos en las claves: el tipo
JSONrepresenta{"a":{"b":1}}y{"a.b":1}con la misma ruta internaa.b. Por lo tanto, una misma fila puede exponer tantoacomoa.bcomo elementos independientes del mismo nivel. Cuando un patch más reciente escribe soloa, la regla de conflicto entre ancestro y descendiente borraa.b; cuando escribe soloa.b, esa misma regla borraa. Para evitarlo, establezcajson_type_escape_dots_in_keys = 1. Con este ajuste, los puntos literales de las claves JSON se representan mediante codificación porcentual (p. ej.,a.bse convierte ena%2Eb), lo que los distingue de las rutas anidadas y elimina el falso conflicto.
json— Columna JSON que se va a agregar.JSONsort_key— Columna comparable que determina qué escritura prevalece para cada ruta. Se conserva la fila con el valor de sort_key más alto.
JSON
Ejemplos
Uso básico con clave de ordenación
Query
Response