mergedJSONPatch
導入バージョン: v26.8.0 JSON 値を後勝ち (last-write-wins) のセマンティクスでマージして集約し、RFC 7396 JSON Merge Patch の中核となるマージ動作を パス単位で実装します。 この集約関数は、ステートを三つ組 (key, value, sorting_key) として保持します。各キー (JSON パス) については、sorting_key に基づく最新の有効なレコードのみが保持されます。JSON 型が動的なスカラーのリーフとして格納するパスでは、オブジェクトの書き込みは子孫パスへフラット化されます。祖先パスへのオブジェクト以外の書き込みは、競合する子孫パスをシャドウ (上書き) します。
明示的に型が宣言されたパス (JSON(a Map(...))、JSON(a Tuple(...))、
JSON(a Variant(...))、JSON(a Dynamic) などで宣言されたもの) は、すべてアトミックな値として扱われます。つまり、パスの値全体が
ディープマージされることはなく、新しいパッチの値で丸ごと置き換えられます。RFC 7396 のディープマージのセマンティクスに従うのは、
型が宣言されていない (動的な) スカラーパスのみです。
sort_key は、各 JSON パスについてどの値が採用されるかを決定します。sort_key が最大の行が
保持されます。競合する 2 つのパッチのソートキーが等しい場合、結果は処理順序に依存し、後から
処理されたパッチが優先されます。同値の場合の優先順位を決定論的に定めるために ORDER BY を当てにしないでください。
制限事項 (ColumnObject から継承) :
-
null による削除: パッチ
{"key": null}ではキーは削除されません。ColumnObjectは挿入時に 値が null のメンバーを破棄するため、この関数は “キーが存在しない” 場合と “キーの値が null である” 場合を区別できません。 -
空オブジェクトによる置換: パッチ
{"a": {}}では、パスaにある古いスカラー値や配列を 置き換えることはできません。ColumnObjectは値が空オブジェクト{}のパスを暗黙的に破棄するため、 新しいパッチは何の効果も持たず、古い値がそのまま残ります。 -
非 Nullable な型付きパスの欠落:
JSONカラムで非 Nullable 型の型付きパスを宣言している場合 (例:JSON(a UInt32))、aを省略した行はその型のデフォルト値 (例:0) で 保存されます。集約関数は “存在しない” 場合と “デフォルト値が明示的に 書き込まれた” 場合を区別できないため、aを省略した新しいパッチによって、古い 0 以外の値が暗黙的に消去されてしまいます。これを避けるには、型付きパスをNullableとして宣言してください (例:JSON(a Nullable(UInt32)))。Nullable な型付きパスの null は “パスが存在しない” ものとして扱われ、正しくスキップされます。 -
型付きパスはすべてアトミック: すべての型付きパス (
Map(K,V)、JSON、Dynamic、Tuple(…)、Variant(…)、Array(…)、その他宣言された任意の型) は単一の値として保存されます。 集約関数はその内容をディープマージせず、値全体をアトミックに置き換えます。 パス単位でディープマージされるのは、動的な (型指定のないスカラー) パスのみです。 -
キー内のドットによる曖昧さ:
JSON型では、{"a":{"b":1}}と{"a.b":1}がどちらも 同じ内部パスa.bで表現されます。そのため、1 つの行でaとa.bの両方が 独立したピアとして現れることがあります。新しいパッチがaのみを書き込むと、祖先/子孫間の競合 ルールによってa.bが消去され、a.bのみを書き込むと、同じルールによってaが消去されます。これを避けるには、json_type_escape_dots_in_keys = 1を設定してください。この設定を有効にすると、JSON キー内のリテラルのドットは パーセントエンコードされ (例:a.bはa%2Ebになります)、ネストされた パスと区別されるため、誤った競合が発生しなくなります。
json— 集約対象の JSON カラム。JSONsort_key— パスごとにどの書き込みを採用するかを決定する、比較可能なカラム。sort_key の値が最大の行が保持されます。
JSON
例
ソートキーを使用した基本的な使い方
Query
Response