docs: complete JSON2 provenance in beta2 review artifacts

Signed-off-by: discord9 <discord9@163.com>
This commit is contained in:
discord9
2026-08-21 14:35:30 +08:00
parent 5a070b30d1
commit fceb668de0
9 changed files with 586 additions and 4 deletions
+5 -1
View File
@@ -12,6 +12,8 @@
## How to read the artifacts
- **[Start here: canonical manual decision index](decisions/README.md)**: priority-ordered semantic concerns, exact differences, exclusions, compatibility impact, and reviewer file pointers.
- PR #8895 mapping: upstream merge `d7f1233f775d54380318d6ad9ff62504a7cbcff1`, head `6b8645bf584a04b45828c7e8d0fb19418db70d2e`; carrier `fed5c80d7e94bd2c8ab1f7ddac8ab205d993156d`; see [#8895 raw evidence](range-diffs/pr-8895.txt) and [JSON2 decision coverage](decisions/json2-mergescan.md).
- PR #8901 mapping: upstream merge `b96ea86a621e7283e77e4e37dd4e3ec8dfc44f73`, head `b450abd46e473a07cb1b42a9c7c62d0b0d551e17`; carrier `5a642091cd2b6185fbe6a08d6f76d8295955152f`; see [#8901 raw evidence](range-diffs/pr-8901.txt) and [JSON2 decision coverage](decisions/json2-mergescan.md).
- PR #8825 mapping: upstream head `bf947141753a9ea554aa1ca31637fdd3ad1429f3`, merge `60c7bbcaf30a0e65ad7fa2b2b8ad0c1199a662b1`; carrier `d18430b874f9c8054747dbf688585cd7d2988e3e`; final head `40e02ff6b62ad3445f7035e437bd9e322c8af31b`. Requested by WenyXu in [Issue #8892 comment 5353700059](https://github.com/GreptimeTeam/greptimedb/issues/8892#issuecomment-5353700059). See [#8825 raw evidence](range-diffs/pr-8825.txt) and [event-context compatibility](decisions/event-context-compatibility.md).
- `range-diffs/pr-<number>.txt`: normally a final one-commit `git range-diff --creation-factor=100` from the upstream merged PR commit to the final aggregate carrier commit. These raw `.txt` files are **unabridged differences-only evidence**, not the complete shipping patch; `pr-8825.txt` is explicitly raw metadata/command evidence because its upstream PR-head object is unavailable locally.
- `patch-id-verdict.tsv`: stable patch IDs and `exact`/`adapted` verdicts. Patch-ID equality means patch equivalence; it does not claim the cherry-pick had no conflict.
@@ -23,7 +25,7 @@
## Scope
The review scope has 33 explicit PRs: the prior 32 plus #8902. Official PR #8921 is now in the release base `2f5e97850e55d86c0ed9eff1719994c88b4450a0`, so it is base-present and is not represented as an aggregate carrier. #8672 and #8699 remain base-present as well. The other explicit PRs are represented by backport mappings; #8825 remains carried by `d18430b874f9c8054747dbf688585cd7d2988e3e`, and #8902 is appended at final head `40e02ff6b62ad3445f7035e437bd9e322c8af31b`. The dependency closure also includes full #8734 and a release-compatible slice of #8392.
The review scope has 36 explicit PRs: the original 31 plus Issue-requested #8825, #8921, #8895, #8901, and #8902. Official PR #8921 is now in the release base `2f5e97850e55d86c0ed9eff1719994c88b4450a0`, so it is base-present and is not represented as an aggregate carrier. #8672 and #8699 remain base-present as well. The other explicit PRs are represented by backport mappings; #8825 remains carried by `d18430b874f9c8054747dbf688585cd7d2988e3e`, and #8902 is appended at final head `40e02ff6b62ad3445f7035e437bd9e322c8af31b`. The dependency closure adds exactly two provenance relationships: full #8734 and a release-compatible slice of #8392, for 38 total provenance relationships.
## Mapping classes
@@ -42,4 +44,6 @@ PR #8824 is accepted by explicit release-owner direction in this backport sessio
The final review range is `2f5e97850e55d86c0ed9eff1719994c88b4450a0..40e02ff6b62ad3445f7035e437bd9e322c8af31b`, a linear 46-commit range. The superseded beta2 base `8eeff8b4417e6fb675a66cecbdba40060322785c` and endpoint `b7fdcb89568dc707c323f8c0a3b9413ec4e889ab` are historical provenance only; all active aggregate carrier fields in the TSV indexes are remapped to the rebased commits. Official #8921 is the release-base commit `2f5e97850e55d86c0ed9eff1719994c88b4450a0`, not a duplicate aggregate carrier.
The three explicit PRs #8672, #8699, and #8921 are base-present; the other explicit PRs have aggregate provenance. Thus the machine-readable indexes contain exactly 36 explicit PR rows plus exactly the two closure rows (#8734 and #8392): 38 unique provenance relationships.
PR #8902 is appended as final carrier `40e02ff6b62ad3445f7035e437bd9e322c8af31b`; its readable decision is [Dictionary group-by fast path](decisions/dictionary-groupby-fast-path.md), and its raw patch comparison is [#8902](range-diffs/pr-8902.txt).
@@ -41,6 +41,6 @@ e61a6df6b2b110badd5755f68010b6439d69ac84 3351de9102b6418207e49c090054b71cc63205
9bf878f562518d30a412138ad4244d7d8e7867e6 668df91d76785b93a00f279916d2584646a56080 fix: adapt event context tests to release channel API
6595b5d7bf1f59587bf89676d420db7371cdc459 922a4f6141ea7ed051b9c891cb05bbcee0b51e69 fix: adapt frontend event context tests
d18430b874f9c8054747dbf688585cd7d2988e3e 60c7bbcaf30a0e65ad7fa2b2b8ad0c1199a662b1 unavailable refactor: share query channel definition
fed5c80d7e94bd2c8ab1f7ddac8ab205d993156d d18430b874f9c8054747dbf688585cd7d2988e3e (unclassified) feat: add JSON2 storage layout settings
5a642091cd2b6185fbe6a08d6f76d8295955152f fed5c80d7e94bd2c8ab1f7ddac8ab205d993156d (unclassified) feat: add JSON2 physical layout primitives
fed5c80d7e94bd2c8ab1f7ddac8ab205d993156d d7f1233f775d54380318d6ad9ff62504a7cbcff1 ba5de162f5dd269aa0081d8d97492c578fc37d05 feat: add JSON2 storage layout settings
5a642091cd2b6185fbe6a08d6f76d8295955152f b96ea86a621e7283e77e4e37dd4e3ec8dfc44f73 a1011136c44b4f6f2520683739fbd845257c0a0e feat: add JSON2 physical layout primitives
40e02ff6b62ad3445f7035e437bd9e322c8af31b d99b0df374eec0329ac3f430e40b80a1e6c6963c; 1a91c76c615afec71239b84af7787a0505bef914 (absorbed) 8c3fca20ce058fd569d436c38bc96e41fc1adbca fix(query): restore columnar group-by for dictionary-encoded tags
1 424e53d8413719e348bc8a694d9d22d3a051ce68 6ffa27bc8e78b5e11b2db3d2a898438446b298be cf8d494dedfcfa5d486291bb05536dfeab4edb98 feat: make frontend heartbeat extensible and lifecycle-safe (#8726)
41 9bf878f562518d30a412138ad4244d7d8e7867e6 668df91d76785b93a00f279916d2584646a56080 fix: adapt event context tests to release channel API
42 6595b5d7bf1f59587bf89676d420db7371cdc459 922a4f6141ea7ed051b9c891cb05bbcee0b51e69 fix: adapt frontend event context tests
43 d18430b874f9c8054747dbf688585cd7d2988e3e 60c7bbcaf30a0e65ad7fa2b2b8ad0c1199a662b1 unavailable refactor: share query channel definition
44 fed5c80d7e94bd2c8ab1f7ddac8ab205d993156d d18430b874f9c8054747dbf688585cd7d2988e3e d7f1233f775d54380318d6ad9ff62504a7cbcff1 (unclassified) ba5de162f5dd269aa0081d8d97492c578fc37d05 feat: add JSON2 storage layout settings
45 5a642091cd2b6185fbe6a08d6f76d8295955152f fed5c80d7e94bd2c8ab1f7ddac8ab205d993156d b96ea86a621e7283e77e4e37dd4e3ec8dfc44f73 (unclassified) a1011136c44b4f6f2520683739fbd845257c0a0e feat: add JSON2 physical layout primitives
46 40e02ff6b62ad3445f7035e437bd9e322c8af31b d99b0df374eec0329ac3f430e40b80a1e6c6963c; 1a91c76c615afec71239b84af7787a0505bef914 (absorbed) 8c3fca20ce058fd569d436c38bc96e41fc1adbca fix(query): restore columnar group-by for dictionary-encoded tags
@@ -52,7 +52,11 @@ These entries are intentionally not given separate concern pages: stable patch-I
| **Exact stable patch-ID** | #8777, #8832, #8787, #8849, #8859, #8889, #8833, #8600, #8808, #8709, #8522, #8739, #8772 | [1dd27e9](https://github.com/GreptimeTeam/greptimedb/commit/1dd27e9162ef5438e9f44b5a48a040f5c399227a), [e80f539](https://github.com/GreptimeTeam/greptimedb/commit/e80f539077616507b04df68a85a67f5da1c8f93e), [0b49947](https://github.com/GreptimeTeam/greptimedb/commit/0b499475dedfa462e9f951e0bb7b516011a195a0), [ab80858](https://github.com/GreptimeTeam/greptimedb/commit/ab808586525877230b9774f2ce29aca590152642), [824c5ac](https://github.com/GreptimeTeam/greptimedb/commit/824c5acfa7cf1865d2c20b77281c6b12e8e73de7), [c894a24](https://github.com/GreptimeTeam/greptimedb/commit/c894a2468c2bbb621bc26bf242046f1c60493460), [4ab29b2](https://github.com/GreptimeTeam/greptimedb/commit/4ab29b22f381156225cf9a50f73e5acc1ba8bbe8), [9c683fc](https://github.com/GreptimeTeam/greptimedb/commit/9c683fccfc11cd5db720b14c7adb22b7d734defd), [1a2e7b8](https://github.com/GreptimeTeam/greptimedb/commit/1a2e7b81679c602ae76f868b66974af9397d4341), [0b6c40e](https://github.com/GreptimeTeam/greptimedb/commit/0b6c40e7f465273ac424beca3475e82f4def7991), [7d68d8d](https://github.com/GreptimeTeam/greptimedb/commit/7d68d8dbe0600b86535293210ec70417e4b2b3d5), [be0985c](https://github.com/GreptimeTeam/greptimedb/commit/be0985cc39c648a35328bf9c340a8d32b814ddc6), [5e0a643](https://github.com/GreptimeTeam/greptimedb/commit/5e0a6436ee91fb4cb48a1a63564e019be02b3e22) (in the same order) | Patch-equivalent to each upstream PR; any cherry-pick conflict is a replay detail, not a semantic delta. | No separate page; see audit TSVs and raw range-diffs |
| **Base-present** | #8672, #8699, #8921 | #8921 official release-base commit `2f5e97850e55d86c0ed9eff1719994c88b4450a0`; no aggregate carrier | Already present in beta2 before this aggregate; no backport patch ships for any of these PRs. | No separate page; see [`README.md`](../README.md) scope |
Exact entries with nearby context can be reviewed from [dependency and baseline adaptations](dependency-and-baseline-adaptations.md) and the [event context page](event-context-compatibility.md). The complete 33-explicit-PR mapping, plus dependency #8734 and slice #8392, is indexed in [`upstream-pr-map.tsv`](../upstream-pr-map.tsv), [`patch-id-verdict.tsv`](../patch-id-verdict.tsv), and [`aggregate-commit-provenance.tsv`](../aggregate-commit-provenance.tsv).
Exact entries with nearby context can be reviewed from [dependency and baseline adaptations](dependency-and-baseline-adaptations.md) and the [event context page](event-context-compatibility.md). The complete 36-explicit-PR mapping (including #8895 and #8901), plus dependency #8734 and slice #8392, is indexed in [`upstream-pr-map.tsv`](../upstream-pr-map.tsv), [`patch-id-verdict.tsv`](../patch-id-verdict.tsv), and [`aggregate-commit-provenance.tsv`](../aggregate-commit-provenance.tsv).
## Final provenance scope
The final review records 36 explicit Issue-requested PR relationships: the original 31 plus #8825, #8921, #8895, #8901, and #8902. Three explicit PRs—#8672, #8699, and #8921—are base-present. The dependency closure adds exactly two relationships: full #8734 and the release-compatible slice of #8392. The indexes therefore contain 38 unique provenance relationships total. The #8895 and #8901 mappings and complete upstream ranges are covered in [JSON2 merge/layout coverage](json2-mergescan.md) and [`manual-deltas.md`](../manual-deltas.md).
## Recorded verification context
@@ -39,3 +39,12 @@ Recorded CI status is documented in the [canonical CI status](README.md#canonica
## Raw audit evidence — unabridged differences only
[`range-diffs/pr-8745.txt`](../range-diffs/pr-8745.txt) is an unabridged patch-to-patch range-diff, not the full shipping patch.
## Additional JSON2 layout provenance
The explicit Issue-requested JSON2 layout PRs are also represented in the machine-readable indexes and have complete raw range evidence:
- **#8895**: upstream merge `d7f1233f775d54380318d6ad9ff62504a7cbcff1`, head `6b8645bf584a04b45828c7e8d0fb19418db70d2e`, complete upstream range `0a6a22033e3ebb4d6c7243874d840558a9eb7216^..6b8645bf584a04b45828c7e8d0fb19418db70d2e`, aggregate carrier `fed5c80d7e94bd2c8ab1f7ddac8ab205d993156d`. The carrier folds the two upstream commits, retains JSON2 DDL/layout settings, and omits the upstream-only >=v1.3.0 compatibility case; it is `adapted`.
- **#8901**: upstream merge `b96ea86a621e7283e77e4e37dd4e3ec8dfc44f73`, head `b450abd46e473a07cb1b42a9c7c62d0b0d551e17`, complete upstream range `6e637fbe58f36643fea40f38d5ff352fe00254f9^..b450abd46e473a07cb1b42a9c7c62d0b0d551e17`, aggregate carrier `5a642091cd2b6185fbe6a08d6f76d8295955152f`. The carrier folds the three upstream commits and is `exact` by stable patch ID.
These are part of the 36 explicit Issue-requested PR relationships. Together with base-present #8672/#8699/#8921 and the two closure relationships (#8734 full, #8392 release-compatible slice), the review contains 38 provenance relationships.
@@ -137,3 +137,19 @@ The canonical reviewer index is [`decisions/README.md`](decisions/README.md). Th
- DataFusion `452cb4b` advances to linear successor `4c8a6bf`, preserving #8842 and adding `DictionaryGroupValuesColumn`.
- GreptimeDB adds `tests-integration/tests/dict_groupby_sst.rs` plus module registration. The test writes 1,200 rows, flushes append-mode flat SST, and exactly verifies six ordered tuples.
- This integration test is not direct fast-path proof: AggregateExec EXPLAIN/metrics do not expose GroupValues identity. Direct `DictionaryGroupValuesColumn` coverage is in the pinned DataFusion fork tests.
### #8895 — adapted, two-commit upstream range folded into one carrier
- Upstream PR range: `0a6a22033e3ebb4d6c7243874d840558a9eb7216` followed by `6b8645bf584a04b45828c7e8d0fb19418db70d2e`; PR head: `6b8645bf584a04b45828c7e8d0fb19418db70d2e`; merge: `d7f1233f775d54380318d6ad9ff62504a7cbcff1`.
- Aggregate carrier: `fed5c80d7e94bd2c8ab1f7ddac8ab205d993156d`.
- The final carrier folds the complete upstream PR range, retains the JSON2 DDL/layout-settings behavior, and omits the upstream-only >=v1.3.0 compatibility-test case. Stable patch IDs therefore differ and the verdict is `adapted`.
- Complete range-diff evidence, including endpoint metadata and the exact generation command, is [`range-diffs/pr-8895.txt`](range-diffs/pr-8895.txt).
### #8901 — exact patch-id, three-commit upstream range folded into one carrier
- Upstream PR range: `6e637fbe58f36643fea40f38d5ff352fe00254f9`, `f2e3d6d6e16c24fdede441cf54ff1c04a3effd91`, and `b450abd46e473a07cb1b42a9c7c62d0b0d551e17`; PR head: `b450abd46e473a07cb1b42a9c7c62d0b0d551e17`; merge: `b96ea86a621e7283e77e4e37dd4e3ec8dfc44f73`.
- Aggregate carrier: `5a642091cd2b6185fbe6a08d6f76d8295955152f`.
- The final carrier folds the complete upstream PR range and retains the JSON2 v2 physical-layout primitives and dependency updates. Its stable patch ID equals the upstream merge patch ID; the changed subject is an aggregate adaptation, so the verdict records `exact` patch equivalence.
- Complete range-diff evidence, including endpoint metadata and the exact generation command, is [`range-diffs/pr-8901.txt`](range-diffs/pr-8901.txt).
## Final provenance scope
The final review records 36 explicit Issue-requested PR relationships: the original 31 plus #8825, #8921, #8895, #8901, and #8902. Of those, #8672, #8699, and #8921 are base-present. The dependency closure contributes exactly two additional relationships—full #8734 and the release-compatible slice of #8392—for 38 unique provenance relationships total.
@@ -30,3 +30,5 @@
8392 cabc2f6cc667291d7bc3dcbb8f9cc82e27bd93a0 f9135380b5591b82c9ec5bbf1706459672bd72db adapted 288b8990db827c0d0f4e11a0f20e0f77fdbf4991 49fecedeb0ec2f57c348307f5fdcfc558de42c59
8825 bf947141753a9ea554aa1ca31637fdd3ad1429f3 d18430b874f9c8054747dbf688585cd7d2988e3e adapted unavailable unavailable
8902 d99b0df374eec0329ac3f430e40b80a1e6c6963c 40e02ff6b62ad3445f7035e437bd9e322c8af31b adapted bdc71e83b0147f1d94f1db4cbe80d0dbf8a6aa58 8c3fca20ce058fd569d436c38bc96e41fc1adbca
8895 d7f1233f775d54380318d6ad9ff62504a7cbcff1 fed5c80d7e94bd2c8ab1f7ddac8ab205d993156d adapted e26d83fb1aab2ee25d7e9d74ba1c42a163507c0d ba5de162f5dd269aa0081d8d97492c578fc37d05
8901 b96ea86a621e7283e77e4e37dd4e3ec8dfc44f73 5a642091cd2b6185fbe6a08d6f76d8295955152f exact a1011136c44b4f6f2520683739fbd845257c0a0e a1011136c44b4f6f2520683739fbd845257c0a0e
1 8729 70470bafbe38df2d3fd21e70e1e7097ffd7317c6 c4baa56b23888fa2a2692b39ae01500d3f295efa adapted 4eb19a8cc40faa86c212e30ca3b1c693594c4e54 e7d70f590b6e541e520d0e5ffe2c6cacf6913c85
30 8392 cabc2f6cc667291d7bc3dcbb8f9cc82e27bd93a0 f9135380b5591b82c9ec5bbf1706459672bd72db adapted 288b8990db827c0d0f4e11a0f20e0f77fdbf4991 49fecedeb0ec2f57c348307f5fdcfc558de42c59
31 8825 bf947141753a9ea554aa1ca31637fdd3ad1429f3 d18430b874f9c8054747dbf688585cd7d2988e3e adapted unavailable unavailable
32 8902 d99b0df374eec0329ac3f430e40b80a1e6c6963c 40e02ff6b62ad3445f7035e437bd9e322c8af31b adapted bdc71e83b0147f1d94f1db4cbe80d0dbf8a6aa58 8c3fca20ce058fd569d436c38bc96e41fc1adbca
33 8895 d7f1233f775d54380318d6ad9ff62504a7cbcff1 fed5c80d7e94bd2c8ab1f7ddac8ab205d993156d adapted e26d83fb1aab2ee25d7e9d74ba1c42a163507c0d ba5de162f5dd269aa0081d8d97492c578fc37d05
34 8901 b96ea86a621e7283e77e4e37dd4e3ec8dfc44f73 5a642091cd2b6185fbe6a08d6f76d8295955152f exact a1011136c44b4f6f2520683739fbd845257c0a0e a1011136c44b4f6f2520683739fbd845257c0a0e
@@ -0,0 +1,330 @@
PR #8895
Upstream PR range: 0a6a22033e3ebb4d6c7243874d840558a9eb7216^..6b8645bf584a04b45828c7e8d0fb19418db70d2e
Aggregate range: fed5c80d7e94bd2c8ab1f7ddac8ab205d993156d^..fed5c80d7e94bd2c8ab1f7ddac8ab205d993156d
Upstream PR merge commit: d7f1233f775d54380318d6ad9ff62504a7cbcff1
Upstream PR head: 6b8645bf584a04b45828c7e8d0fb19418db70d2e
Aggregate carrier: fed5c80d7e94bd2c8ab1f7ddac8ab205d993156d
Endpoint metadata: the upstream PR contains 0a6a22033e3ebb4d6c7243874d840558a9eb7216 and 6b8645bf584a04b45828c7e8d0fb19418db70d2e; GitHub records d7f1233f775d54380318d6ad9ff62504a7cbcff1 as its merge commit. Beta2 carries the requested behavior in one final carrier.
Adaptation/folding notes: the carrier folds both upstream PR commits into one commit, changes the subject to the exact aggregate subject, and omits the upstream-only compatibility-test case (which targets >=v1.3.0). The JSON2 layout-settings implementation is retained; this is an adapted backport, not a claim of exact commit identity.
Command: git range-diff --creation-factor=100 0a6a22033e3ebb4d6c7243874d840558a9eb7216^..6b8645bf584a04b45828c7e8d0fb19418db70d2e fed5c80d7e94bd2c8ab1f7ddac8ab205d993156d^..fed5c80d7e94bd2c8ab1f7ddac8ab205d993156d
1: 0a6a22033 ! 1: fed5c80d7 refactor(json2): add JSON2 storage layout settings
@@
## Metadata ##
-Author: luofucong <luofc@foxmail.com>
+Author: discord9 <discord9@163.com>
## Commit message ##
- refactor(json2): add JSON2 storage layout settings
+ feat: add JSON2 storage layout settings
- Signed-off-by: luofucong <luofc@foxmail.com>
+ Signed-off-by: discord9 <discord9@163.com>
## src/datatypes/src/error.rs ##
@@ src/datatypes/src/error.rs: pub enum Error {
@@ src/datatypes/src/json.rs: pub struct JsonContext<'a> {
+ })
+ }
+
-+ #[cfg(test)]
-+ fn new(type_hints: Vec<JsonTypeHint>) -> Self {
-+ Self {
-+ type_hints,
-+ max_auto_expanded_paths: None,
-+ }
-+ }
-+
+ pub fn type_hints(&self) -> &[JsonTypeHint] {
+ &self.type_hints
+ }
@@ src/datatypes/src/json.rs: impl JsonSettings {
+ .fail();
+ }
+ };
-+ insert_type_hint(&mut object, &hint.path, data_type)?;
++ validate_type_hint(&mut object, &hint.path, data_type)?;
+ }
+ Ok(())
+}
+
-+fn insert_type_hint(
++fn validate_type_hint(
+ object: &mut JsonObjectType,
+ path: &[String],
+ data_type: JsonNativeType,
@@ src/datatypes/src/json.rs: impl JsonSettings {
+ }
+ .fail();
+ };
-+ insert_type_hint(child, path, data_type)
++ validate_type_hint(child, path, data_type)
+}
+
impl<'a> JsonContext<'a> {
@@ src/datatypes/src/json.rs: impl JsonSettings {
@@ src/datatypes/src/json.rs: mod tests {
}
+ #[test]
+- fn test_json_settings_forward_compatibility() {
++ fn test_json_settings_forward_compatibility()
++ -> std::result::Result<(), Box<dyn std::error::Error>> {
+ let json_str = r#"{
+ "type_hints": [
+ {
+@@ src/datatypes/src/json.rs: mod tests {
+ ]
+ }"#;
+
+- let deserialized = serde_json::from_str::<JsonSettings>(json_str).unwrap();
++ let deserialized = serde_json::from_str::<JsonSettings>(json_str)?;
+
+- assert_eq!(
+- deserialized,
+- JsonSettings::new(vec![
++ let expected = JsonSettings::try_new(
++ vec![
+ JsonTypeHint {
+ path: vec!["user".to_string(), "age".to_string()],
+ data_type: ConcreteDataType::int64_datatype(),
+@@ src/datatypes/src/json.rs: mod tests {
+ default_constraint: None,
+ inverted_index: false,
+ },
+- ])
+- );
++ ],
++ None,
++ )?;
++ assert_eq!(deserialized, expected);
++ Ok(())
+ }
+
#[test]
- fn test_json_settings_ser_de() {
- let settings = JsonSettings::new(vec![
@@ src/datatypes/src/json.rs: mod tests {
+ );
}
+ #[test]
+@@ src/datatypes/src/json.rs: mod tests {
+ }
+
+ #[test]
+- fn test_encode_json_respects_type_hint() {
+- let settings = JsonSettings::new(vec![JsonTypeHint {
++ fn test_encode_json_respects_type_hint() -> Result<()> {
++ let type_hints = vec![JsonTypeHint {
+ path: vec!["age".to_string()],
+ data_type: ConcreteDataType::int64_datatype(),
+ nullable: false,
+ default_constraint: None,
+ inverted_index: false,
+- }]);
++ }];
++ let settings = JsonSettings::try_new(type_hints, None)?;
+
+ let result = settings
+ .encode(json!({
+@@ src/datatypes/src/json.rs: mod tests {
+ }))
+ .unwrap_err();
+ assert!(err.to_string().contains("does not match JSON2 type hint"));
++ Ok(())
+ }
+
+ #[test]
+- fn test_encode_json_respects_unsigned_type_hint() {
+- let settings = JsonSettings::new(vec![JsonTypeHint {
++ fn test_encode_json_respects_unsigned_type_hint() -> Result<()> {
++ let type_hints = vec![JsonTypeHint {
+ path: vec!["count".to_string()],
+ data_type: ConcreteDataType::uint64_datatype(),
+ nullable: false,
+ default_constraint: None,
+ inverted_index: false,
+- }]);
++ }];
++ let settings = JsonSettings::try_new(type_hints, None)?;
+
+ let result = settings
+ .encode(json!({
+@@ src/datatypes/src/json.rs: mod tests {
+ }))
+ .unwrap_err();
+ assert!(err.to_string().contains("does not match JSON2 type hint"));
++ Ok(())
+ }
+
+ #[test]
+- fn test_encode_json_fills_missing_type_hint_with_default() {
+- let settings = JsonSettings::new(vec![JsonTypeHint {
++ fn test_encode_json_fills_missing_type_hint_with_default() -> Result<()> {
++ let type_hints = vec![JsonTypeHint {
+ path: vec!["user".to_string(), "age".to_string()],
+ data_type: ConcreteDataType::int64_datatype(),
+ nullable: false,
+ default_constraint: Some(ColumnDefaultConstraint::Value(Value::Int64(7))),
+ inverted_index: false,
+- }]);
++ }];
++ let settings = JsonSettings::try_new(type_hints, None)?;
+
+ let result = settings
+ .encode(json!({}))
+@@ src/datatypes/src/json.rs: mod tests {
+ panic!("Expected user Struct value");
+ };
+ assert_eq!(struct_field_value(user, "age"), &Value::Int64(7));
++ Ok(())
+ }
+
+ #[test]
+- fn test_encode_json_fills_missing_nullable_type_hint_with_null() {
+- let settings = JsonSettings::new(vec![JsonTypeHint {
++ fn test_encode_json_fills_missing_nullable_type_hint_with_null() -> Result<()> {
++ let type_hints = vec![JsonTypeHint {
+ path: vec!["user".to_string(), "name".to_string()],
+ data_type: ConcreteDataType::string_datatype(),
+ nullable: true,
+ default_constraint: None,
+ inverted_index: false,
+- }]);
++ }];
++ let settings = JsonSettings::try_new(type_hints, None)?;
+
+ let result = settings
+ .encode(json!({ "user": {} }))
+@@ src/datatypes/src/json.rs: mod tests {
+ panic!("Expected user Struct value");
+ };
+ assert_eq!(struct_field_value(user, "name"), &Value::Null);
++ Ok(())
+ }
+
+ #[test]
+- fn test_encode_json_rejects_missing_non_null_type_hint() {
+- let settings = JsonSettings::new(vec![JsonTypeHint {
++ fn test_encode_json_rejects_missing_non_null_type_hint() -> Result<()> {
++ let type_hints = vec![JsonTypeHint {
+ path: vec!["user".to_string(), "age".to_string()],
+ data_type: ConcreteDataType::int64_datatype(),
+ nullable: false,
+ default_constraint: None,
+ inverted_index: false,
+- }]);
++ }];
++ let settings = JsonSettings::try_new(type_hints, None)?;
+
+ let err = settings.encode(json!({})).unwrap_err();
+ assert!(
+ err.to_string()
+ .contains("missing non-null JSON2 type hint path user.age")
+ );
++ Ok(())
+ }
+
+ #[test]
+- fn test_encode_json_merges_missing_type_hint_prefix() {
+- let settings = JsonSettings::new(vec![
++ fn test_encode_json_merges_missing_type_hint_prefix() -> Result<()> {
++ let type_hints = vec![
+ JsonTypeHint {
+ path: vec!["user".to_string(), "age".to_string()],
+ data_type: ConcreteDataType::int64_datatype(),
+@@ src/datatypes/src/json.rs: mod tests {
+ ))),
+ inverted_index: false,
+ },
+- ]);
++ ];
++ let settings = JsonSettings::try_new(type_hints, None)?;
+
+- let result = settings
+- .encode(json!({}))
+- .unwrap()
+- .into_json_inner()
+- .unwrap();
++ let result = settings.encode(json!({}))?.into_json_inner().unwrap();
+
+ let Value::Struct(root) = result else {
+ panic!("Expected Struct value");
+@@ src/datatypes/src/json.rs: mod tests {
+ struct_field_value(user, "name"),
+ &Value::String("unknown".into())
+ );
++ Ok(())
+ }
+
#[test]
## src/sql/src/error.rs ##
@@ src/sql/src/statements/create.rs: AS SELECT number FROM numbers_input where numb
};
let result = extensions.build_vector_index_options();
assert!(result.is_ok());
-
- ## tests/compatibility/cases/json2_storage_layout_settings/case.toml (new) ##
-@@
-+name = "json2_storage_layout_settings"
-+reason = "Verify JSON2 storage layout settings in Arrow extension metadata survive restarts and upgrades."
-+introduced_by = "PR #8895"
-+topologies = ["distributed", "standalone"]
-+from_range = [">=v1.3.0"]
-+to_range = [">=v1.3.0"]
-+features = ["json2", "table", "metadata", "read"]
-+owner = "query"
-
- ## tests/compatibility/cases/json2_storage_layout_settings/setup.sql (new) ##
-@@
-+CREATE TABLE t_json2_storage_layout_settings (
-+ ts TIMESTAMP TIME INDEX,
-+ j JSON2(max_auto_expanded_paths = 0)
-+) WITH (
-+ 'append_mode' = 'true'
-+);
-+
-+INSERT INTO t_json2_storage_layout_settings VALUES
-+ ('2026-08-17 00:00:00+0000', '{"a": 1}');
-+
-+ADMIN FLUSH_TABLE('t_json2_storage_layout_settings');
-
- ## tests/compatibility/cases/json2_storage_layout_settings/verify.result (new) ##
-@@
-+SELECT j.a AS a
-+FROM t_json2_storage_layout_settings;
-+
-++---+
-+| a |
-++---+
-+| 1 |
-++---+
-+
-+SHOW CREATE TABLE t_json2_storage_layout_settings;
-+
-++---------------------------------+----------------------------------------------------------------+
-+| Table | Create Table |
-++---------------------------------+----------------------------------------------------------------+
-+| t_json2_storage_layout_settings | CREATE TABLE IF NOT EXISTS "t_json2_storage_layout_settings" ( |
-+| | "ts" TIMESTAMP(3) NOT NULL, |
-+| | "j" JSON2( |
-+| | max_auto_expanded_paths = 0 |
-+| | ) NULL, |
-+| | TIME INDEX ("ts") |
-+| | ) |
-+| | |
-+| | ENGINE=mito |
-+| | WITH( |
-+| | append_mode = 'true' |
-+| | ) |
-++---------------------------------+----------------------------------------------------------------+
-
- ## tests/compatibility/cases/json2_storage_layout_settings/verify.sql (new) ##
-@@
-+SELECT j.a AS a
-+FROM t_json2_storage_layout_settings;
-+
-+SHOW CREATE TABLE t_json2_storage_layout_settings;
2: 6b8645bf5 < -: --------- resolve PR comments
@@ -0,0 +1,215 @@
PR #8901
Upstream PR range: 6e637fbe58f36643fea40f38d5ff352fe00254f9^..b450abd46e473a07cb1b42a9c7c62d0b0d551e17
Aggregate range: 5a642091cd2b6185fbe6a08d6f76d8295955152f^..5a642091cd2b6185fbe6a08d6f76d8295955152f
Upstream PR merge commit: b96ea86a621e7283e77e4e37dd4e3ec8dfc44f73
Upstream PR head: b450abd46e473a07cb1b42a9c7c62d0b0d551e17
Aggregate carrier: 5a642091cd2b6185fbe6a08d6f76d8295955152f
Endpoint metadata: the upstream PR contains 6e637fbe58f36643fea40f38d5ff352fe00254f9, f2e3d6d6e16c24fdede441cf54ff1c04a3effd91, and b450abd46e473a07cb1b42a9c7c62d0b0d551e17; GitHub records b96ea86a621e7283e77e4e37dd4e3ec8dfc44f73 as its merge commit. Beta2 carries the requested behavior in one final carrier.
Adaptation/folding notes: the carrier folds all three upstream PR commits into one commit and changes the subject to the exact aggregate subject. The JSON2 v2 physical-layout primitives and dependency updates are retained; release lock/context resolution is represented by the final carrier. This is an exact stable patch-ID replay with a folded commit message.
Command: git range-diff --creation-factor=100 6e637fbe58f36643fea40f38d5ff352fe00254f9^..b450abd46e473a07cb1b42a9c7c62d0b0d551e17 5a642091cd2b6185fbe6a08d6f76d8295955152f^..5a642091cd2b6185fbe6a08d6f76d8295955152f
1: 6e637fbe5 ! 1: 5a642091c refactor(json2): add JSON2 v2 physical layout primitives
@@
## Metadata ##
-Author: luofucong <luofc@foxmail.com>
+Author: discord9 <discord9@163.com>
## Commit message ##
- refactor(json2): add JSON2 v2 physical layout primitives
+ feat: add JSON2 physical layout primitives
- Signed-off-by: luofucong <luofc@foxmail.com>
+ Signed-off-by: discord9 <discord9@163.com>
## Cargo.lock ##
@@ Cargo.lock: dependencies = [
@@ src/datatypes/Cargo.toml: jsonb.workspace = true
serde.workspace = true
## src/datatypes/src/extension/json.rs ##
-@@
- use std::collections::HashMap;
- use std::sync::Arc;
-
-+#[cfg(test)]
-+use arrow_schema::FieldRef;
+@@ src/datatypes/src/extension/json.rs: use std::sync::Arc;
use arrow_schema::extension::{
EXTENSION_TYPE_METADATA_KEY, EXTENSION_TYPE_NAME_KEY, ExtensionType,
};
- use arrow_schema::{ArrowError, DataType, Field};
-+#[cfg(test)]
+-use arrow_schema::{ArrowError, DataType, Field};
++use arrow_schema::{ArrowError, DataType, Field, FieldRef};
+use parquet_variant_compute::VariantType;
use serde::{Deserialize, Serialize};
-use snafu::ResultExt;
-+#[cfg(test)]
-+use snafu::OptionExt;
+use snafu::{ResultExt, ensure};
+use crate::error::InvalidJson2LayoutSnafu;
@@ src/datatypes/src/extension/json.rs
const LEGACY_JSON_STRUCTURE_SETTINGS_KEY: &str = "json_structure_settings";
+const JSON2_LAYOUT_V1: u8 = 1;
+const JSON2_LAYOUT_V2: u8 = 2;
-+
+
+-#[derive(Debug, Clone, Serialize, Deserialize, Default)]
+/// Parsed physical layout of a JSON2 Arrow root field.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Json2PhysicalLayout {
@@ src/datatypes/src/extension/json.rs
+}
+
+impl Json2PhysicalLayout {
-+ /// Parses and validates the JSON2 layout version from a root field.
++ /// Parses the JSON2 layout version from a root field.
++ ///
++ /// The version is read from the extension metadata; missing metadata
++ /// defaults to V1.
++ ///
++ /// Supported versions:
++ /// - V1
++ /// - V2
++ ///
++ /// Errors when the field is not a JSON2 extension or the version is not
++ /// one of the supported versions.
+ pub fn try_from_root(field: &Field) -> crate::error::Result<Self> {
+ ensure!(
+ is_json2_extension_type(field),
@@ src/datatypes/src/extension/json.rs
+}
+
+/// Returns the remainder field of a JSON2 v2 root.
-+#[cfg(test)]
-+fn json2_remainder_field(field: &Field) -> crate::error::Result<&FieldRef> {
-+ if !Json2PhysicalLayout::try_from_root(field)?.is_version_2() {
-+ return InvalidJson2LayoutSnafu {
-+ reason: format!("JSON2 root '{}' is not layout v2", field.name()),
-+ }
-+ .fail();
++pub(crate) fn json2_remainder_field(field: &Field) -> crate::error::Result<Option<&FieldRef>> {
++ let layout = Json2PhysicalLayout::try_from_root(field)?;
++ if !layout.is_version_2() {
++ return Ok(None);
+ }
-
--#[derive(Debug, Clone, Serialize, Deserialize, Default)]
-+ let DataType::Struct(fields) = field.data_type() else {
-+ return InvalidJson2LayoutSnafu {
-+ reason: format!(
-+ "expecting the Struct datatype, actual: '{}'",
-+ field.data_type(),
-+ ),
-+ }
-+ .fail();
++
++ let remainder = if let DataType::Struct(fields) = field.data_type() {
++ fields
++ .iter()
++ .find(|x| x.name() == JSON2_REMAINDER_FIELD_NAME)
++ } else {
++ None
+ };
-+ let remainder = fields
-+ .iter()
-+ .find(|x| x.name() == JSON2_REMAINDER_FIELD_NAME)
-+ .context(InvalidJson2LayoutSnafu {
-+ reason: "remainder field not found",
++
++ if let Some(remainder) = remainder {
++ let _ = remainder.try_extension_type::<VariantType>().map_err(|e| {
++ InvalidJson2LayoutSnafu {
++ reason: e.to_string(),
++ }
++ .build()
+ })?;
-+ let _ = remainder.try_extension_type::<VariantType>().map_err(|e| {
-+ InvalidJson2LayoutSnafu {
-+ reason: e.to_string(),
-+ }
-+ .build()
-+ })?;
++ }
+ Ok(remainder)
+}
+
@@ src/datatypes/src/extension/json.rs: mod tests {
+ JsonSettings::default(),
+ ))));
+ assert!(Json2PhysicalLayout::try_from_root(&v2)?.is_version_2());
-+ let remainder = json2_remainder_field(&v2)?;
++ let remainder = json2_remainder_field(&v2)?.unwrap();
+ assert_eq!(JSON2_REMAINDER_FIELD_NAME, remainder.name());
+ Ok(())
+ }
@@ src/datatypes/src/extension/json.rs: mod tests {
+ Json2ExtensionType::new(Arc::new(JsonMetadata::new_v2(JsonSettings::default())));
+ let missing = Field::new("data", DataType::Struct(Fields::empty()), true)
+ .with_extension_type(metadata.clone());
-+ assert!(json2_remainder_field(&missing).is_err());
++ assert!(json2_remainder_field(&missing).is_ok_and(|x| x.is_none()));
+
+ let invalid = Field::new(
+ "data",
@@ src/datatypes/src/vectors/json/array.rs: use crate::data_type::ConcreteDataType;
use crate::error::{
AlignJsonArraySnafu, ArrowComputeSnafu, InvalidJsonSnafu, InvalidJsonbSnafu, Result,
};
-+use crate::extension::json::{JSON2_REMAINDER_FIELD_NAME, Json2PhysicalLayout};
++use crate::extension::json::{JSON2_REMAINDER_FIELD_NAME, json2_remainder_field};
use crate::json::value::{decode_json_variant, encode_serde_json_as_jsonb};
use crate::prelude::{DataType as _, Value as GreptimeValue};
use crate::value::{ListValue, StructValue};
@@ src/datatypes/src/vectors/json/array.rs: impl JsonArray<'_> {
}
+ /// Projects a physical JSON2 array to a logical query type.
-+ pub fn project_json2(&self, field: &Field, target: &DataType) -> Result<ArrayRef> {
-+ let layout = Json2PhysicalLayout::try_from_root(field)?;
-+ if !layout.is_version_2() {
-+ return self.project_to(target);
-+ }
-+
-+ let has_remainder = match field.data_type() {
-+ DataType::Struct(fields) => fields
-+ .iter()
-+ .any(|x| x.name() == JSON2_REMAINDER_FIELD_NAME),
-+ _ => false,
-+ };
-+ if !has_remainder {
-+ return self.project_to(target);
++ ///
++ /// TODO(LFC) Supersede `project_to_v2` to `project_to`.
++ pub fn project_to_v2(&self, field: &Field, target: &DataType) -> Result<ArrayRef> {
++ if json2_remainder_field(field)?.is_some() {
++ project_json_values(self.json2_values()?, target)
++ } else {
++ self.project_to(target)
+ }
-+
-+ project_json_values(self.json2_values()?, target)
+ }
+
+ fn json2_values(&self) -> Result<Vec<Value>> {
@@ src/datatypes/src/vectors/json/array.rs: mod test {
+ ]
+ .into(),
+ );
-+ let projected = JsonArray::from(&array).project_json2(&field, &target)?;
++ let projected = JsonArray::from(&array).project_to_v2(&field, &target)?;
+ assert_eq!(
+ json!({"cold": 1, "count": 42}),
+ JsonArray::from(&projected).try_get_value(0)?
@@ src/datatypes/src/vectors/json/array.rs: mod test {
+ Json2ExtensionType::new(Arc::new(JsonMetadata::new_v2(JsonSettings::default()))),
+ );
+
-+ let projected = JsonArray::from(&array).project_json2(&field, field.data_type())?;
++ let projected = JsonArray::from(&array).project_to_v2(&field, field.data_type())?;
+ assert!(Arc::ptr_eq(&array, &projected));
+ Ok(())
+ }
2: f2e3d6d6e < -: --------- resolve PR comments
3: b450abd46 < -: --------- fix ci
@@ -34,3 +34,5 @@
8825 bf947141753a9ea554aa1ca31637fdd3ad1429f3 MERGED https://github.com/GreptimeTeam/greptimedb/pull/8825 refactor: share query channel definition
8902 8d887ddd00d67699d0fb873cda11eb50b5771555 MERGED https://github.com/GreptimeTeam/greptimedb/pull/8902 fix(query): restore columnar group-by for dictionary-encoded tags (PR head 1a91c76c615afec71239b84af7787a0505bef914; range starts d99b0df374eec0329ac3f430e40b80a1e6c6963c)
8921 2f5e97850e55d86c0ed9eff1719994c88b4450a0 BASE-PRESENT (official release base) https://github.com/GreptimeTeam/greptimedb/pull/8921 fix: clear pooled Prometheus Remote Write decoder state
8895 d7f1233f775d54380318d6ad9ff62504a7cbcff1 MERGED https://github.com/GreptimeTeam/greptimedb/pull/8895 refactor(json2): support JSON2 storage layout settings in DDL
8901 b96ea86a621e7283e77e4e37dd4e3ec8dfc44f73 MERGED https://github.com/GreptimeTeam/greptimedb/pull/8901 refactor(json2): add JSON2 v2 physical layout primitives
1 8729 70470bafbe38df2d3fd21e70e1e7097ffd7317c6 MERGED https://github.com/GreptimeTeam/greptimedb/pull/8729 fix(flow): fix flow stats aggregation and df_plan_to_sql quoting
34 8825 bf947141753a9ea554aa1ca31637fdd3ad1429f3 MERGED https://github.com/GreptimeTeam/greptimedb/pull/8825 refactor: share query channel definition
35 8902 8d887ddd00d67699d0fb873cda11eb50b5771555 MERGED https://github.com/GreptimeTeam/greptimedb/pull/8902 fix(query): restore columnar group-by for dictionary-encoded tags (PR head 1a91c76c615afec71239b84af7787a0505bef914; range starts d99b0df374eec0329ac3f430e40b80a1e6c6963c)
36 8921 2f5e97850e55d86c0ed9eff1719994c88b4450a0 BASE-PRESENT (official release base) https://github.com/GreptimeTeam/greptimedb/pull/8921 fix: clear pooled Prometheus Remote Write decoder state
37 8895 d7f1233f775d54380318d6ad9ff62504a7cbcff1 MERGED https://github.com/GreptimeTeam/greptimedb/pull/8895 refactor(json2): support JSON2 storage layout settings in DDL
38 8901 b96ea86a621e7283e77e4e37dd4e3ec8dfc44f73 MERGED https://github.com/GreptimeTeam/greptimedb/pull/8901 refactor(json2): add JSON2 v2 physical layout primitives