Skip to main content

mergedJSONPatch

Introduit dans : v26.8.0 Agrège des valeurs JSON en les fusionnant selon une sémantique « last-write-wins » (la dernière écriture l’emporte), en implémentant au niveau du path le comportement de fusion de base de la RFC 7396 JSON Merge Patch. La fonction d’agrégation stocke son état sous forme de triplets (key, value, sorting_key), où chaque clé (chemin JSON) ne conserve que le dernier enregistrement effectif selon sorting_key. Les écritures d’objets sont aplaties en chemins descendants pour les chemins que le type JSON stocke comme feuilles scalaires dynamiques. Les écritures autres que des objets sur un ancêtre masquent les descendants en conflit. Chaque chemin explicitement typé (déclaré avec JSON(a Map(...)), JSON(a Tuple(...)), JSON(a Variant(...)), JSON(a Dynamic), etc.) est traité comme une valeur atomique : la valeur du chemin est intégralement remplacée par le patch le plus récent au lieu d’être fusionnée en profondeur. Seuls les chemins scalaires non typés (dynamiques) suivent la sémantique de fusion profonde de la RFC 7396. Le sort_key détermine quelle valeur l’emporte pour chaque chemin JSON. La ligne ayant le sort_key le plus élevé est conservée. Si deux patchs en conflit ont des clés de tri identiques, le résultat dépend de l’ordre : le patch traité en dernier l’emporte. Ne comptez pas sur ORDER BY pour départager les égalités de manière déterministe. LIMITATIONS (héritées de ColumnObject)\u00a0:
  1. Suppression par null : un patch {"key": null} ne supprime pas la clé. ColumnObject supprime les membres de valeur null lors de l’insertion ; la fonction ne peut donc pas distinguer “clé absente” de “clé à null”.
  2. Remplacement par un objet vide : un patch {"a": {}} ne peut pas remplacer une ancienne valeur scalaire ou un ancien tableau au chemin a. ColumnObject supprime silencieusement les chemins dont la valeur est un objet vide {} ; le patch le plus récent n’apporte donc rien et l’ancienne valeur est conservée.
  3. Absence d’un chemin typé non Nullable : lorsqu’une colonne JSON déclare un chemin typé avec un type non nullable (par exemple, JSON(a UInt32)), une ligne qui omet a est stockée avec la valeur par défaut du type (par exemple, 0). L’agrégat ne peut pas distinguer “absent” de “explicitement écrit avec la valeur par défaut” : un patch plus récent qui omet a efface donc silencieusement une ancienne valeur non nulle. Pour éviter cela, déclarez les chemins typés comme Nullable (par exemple, JSON(a Nullable(UInt32))). Un null dans un chemin typé nullable est traité comme “chemin absent” et correctement ignoré.
  4. Tous les chemins typés sont atomiques : chaque chemin typé (Map(K,V), JSON, Dynamic, Tuple(…), Variant(…), Array(…) ou tout autre type déclaré) est stocké sous forme de valeur unique. L’agrégat remplace la valeur entière de manière atomique au lieu de fusionner son contenu en profondeur. Seuls les chemins dynamiques (non typés, scalaires) sont fusionnés en profondeur, chemin par chemin.
  5. Ambiguïté des points dans les clés : le type JSON représente {"a":{"b":1}} et {"a.b":1} avec le même chemin interne a.b. Une même ligne peut donc exposer à la fois a et a.b comme des chemins homologues indépendants. Lorsqu’un patch plus récent écrit uniquement a, la règle de conflit ancêtre/descendant efface a.b ; lorsqu’il écrit uniquement a.b, la même règle efface a. Pour éviter cela, définissez json_type_escape_dots_in_keys = 1. Avec ce paramètre, les points littéraux dans les clés JSON sont encodés en pourcentage (par exemple, a.b devient a%2Eb), ce qui les distingue des chemins imbriqués et élimine le faux conflit.
Syntaxe
Arguments
  • json — Colonne JSON à agréger. JSON
  • sort_key — Colonne comparable qui détermine quelle écriture l’emporte pour chaque path. La ligne dont la valeur de sort_key est la plus élevée est conservée.
Valeur renvoyée Renvoie un seul objet JSON résultant de la fusion de tous les objets JSON fournis en entrée. JSON Exemples Utilisation de base avec une clé de tri
Query
Response
Dernière modification le 14 octobre 2026