From 837b701e687228c19c4ba5371fabca2810192afc Mon Sep 17 00:00:00 2001 From: fys <40801205+fengys1996@users.noreply.github.com> Date: Thu, 23 Jul 2026 10:29:31 +0000 Subject: [PATCH] fix(json2): encode deeply nested values as jsonb (#8612) * fix(json2): encode deeply nested values as jsonb Signed-off-by: fys * add more sqlness Signed-off-by: fys * some changes Signed-off-by: fys * fix(json2): limit type hint path depth Signed-off-by: fys --------- Signed-off-by: fys --- src/datatypes/src/json.rs | 13 +- src/datatypes/src/vectors/json/array.rs | 41 +++ src/sql/src/parsers/create_parser/json.rs | 9 + .../standalone/common/types/json/json2.result | 65 ++++- .../standalone/common/types/json/json2.sql | 27 ++ .../types/json/json2_deep_nesting.result | 234 ++++++++++++++++++ .../common/types/json/json2_deep_nesting.sql | 101 ++++++++ .../common/types/json/json2_type_hints.result | 28 +++ .../common/types/json/json2_type_hints.sql | 22 ++ 9 files changed, 534 insertions(+), 6 deletions(-) create mode 100644 tests/cases/standalone/common/types/json/json2_deep_nesting.result create mode 100644 tests/cases/standalone/common/types/json/json2_deep_nesting.sql diff --git a/src/datatypes/src/json.rs b/src/datatypes/src/json.rs index 54bd4fe97a..48a9174020 100644 --- a/src/datatypes/src/json.rs +++ b/src/datatypes/src/json.rs @@ -30,11 +30,14 @@ use snafu::ResultExt; use crate::data_type::ConcreteDataType; use crate::error::{self, Result, UnsupportedJsonTypeSnafu}; -use crate::json::value::{JsonValue, JsonVariant}; +use crate::json::value::{JsonValue, JsonVariant, encode_serde_json_as_jsonb}; use crate::schema::ColumnDefaultConstraint; use crate::types::json_type::JsonNativeType; use crate::value::{ListValue, StructValue, Value}; +/// Maximum number of JSON container levels represented as nested Arrow types. +pub const JSON2_MAX_STRUCTURED_DEPTH: usize = 50; + /// JSON2 settings stored in column schema metadata and represented through /// Arrow extension metadata. #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] @@ -341,6 +344,14 @@ fn encode_json_array_with_context<'a>( /// Helper function to encode a JSON value to a Value and determine its ConcreteDataType with context fn encode_json_value_with_context(json: Json, context: &mut JsonContext) -> Result { + if context.path.len() >= JSON2_MAX_STRUCTURED_DEPTH + && matches!(&json, Json::Object(_) | Json::Array(_)) + { + return Ok(JsonValue::new(JsonVariant::Variant( + encode_serde_json_as_jsonb(json), + ))); + } + match json { Json::Null => Ok(JsonValue::null()), Json::Bool(b) => Ok(b.into()), diff --git a/src/datatypes/src/vectors/json/array.rs b/src/datatypes/src/vectors/json/array.rs index e08b805c16..3b52064299 100644 --- a/src/datatypes/src/vectors/json/array.rs +++ b/src/datatypes/src/vectors/json/array.rs @@ -199,6 +199,23 @@ impl JsonArray<'_> { return Ok(self.inner.clone()); } + if to_type == &DataType::Utf8View { + let values = (0..self.inner.len()) + .map(|i| { + if self.inner.is_null(i) { + return Ok(None); + } + let value = match self.try_get_value(i)? { + Value::Null => return Ok(None), + Value::String(value) => value, + value => value.to_string(), + }; + Ok(Some(value)) + }) + .collect::>>()?; + return Ok(Arc::new(StringViewArray::from(values)) as ArrayRef); + } + if from_type.is_binary() && !to_type.is_binary() { return self.decode_variant(to_type); } @@ -213,6 +230,7 @@ impl JsonArray<'_> { let formatter = ArrayFormatter::try_new(&self.inner, &FormatOptions::default()) .context(ArrowComputeSnafu)?; + let values = (0..self.inner.len()) .map(|i| { self.inner @@ -390,6 +408,29 @@ mod test { Ok(()) } + #[test] + fn test_cast_variant_to_utf8_view_preserves_json_null() -> Result<()> { + let encode = |json: &[u8]| jsonb::parse_value(json).unwrap().to_vec(); + let json_null = encode(b"null"); + let object = encode(br#"{"value":1}"#); + let string = encode(br#""text""#); + let variants: ArrayRef = Arc::new(BinaryArray::from(vec![ + Some(json_null.as_slice()), + Some(object.as_slice()), + Some(string.as_slice()), + None, + ])); + + let casted = JsonArray::from(&variants).try_cast(&DataType::Utf8View)?; + let casted = casted.as_string_view(); + assert!(casted.is_null(0)); + assert_eq!(casted.value(1), r#"{"value":1}"#); + assert_eq!(casted.value(2), "text"); + assert!(casted.is_null(3)); + + Ok(()) + } + #[test] fn test_align_json_array() -> Result<()> { struct TestCase { diff --git a/src/sql/src/parsers/create_parser/json.rs b/src/sql/src/parsers/create_parser/json.rs index fd8225cc9b..e2f493719c 100644 --- a/src/sql/src/parsers/create_parser/json.rs +++ b/src/sql/src/parsers/create_parser/json.rs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +use datatypes::json::JSON2_MAX_STRUCTURED_DEPTH; use snafu::{ResultExt, ensure}; use sqlparser::ast::{DataType, ExactNumberInfo, Expr, ObjectName, UnaryOperator}; use sqlparser::dialect::keywords::Keyword; @@ -76,6 +77,14 @@ fn parse_json2_type_hints(parser: &mut Parser<'_>) -> Result> fn parse_json2_type_hint(parser: &mut Parser<'_>) -> Result { let path = parse_json2_path(parser)?; + ensure!( + path.len() <= JSON2_MAX_STRUCTURED_DEPTH, + InvalidSqlSnafu { + msg: format!( + "JSON2 type hint path cannot exceed {JSON2_MAX_STRUCTURED_DEPTH} segments" + ), + } + ); let data_type = parser.parse_data_type().context(SyntaxSnafu)?; let data_type = normalize_json2_type_hint_type(data_type)?; diff --git a/tests/cases/standalone/common/types/json/json2.result b/tests/cases/standalone/common/types/json/json2.result index 2f7cad0545..56e2f16af1 100644 --- a/tests/cases/standalone/common/types/json/json2.result +++ b/tests/cases/standalone/common/types/json/json2.result @@ -218,15 +218,15 @@ select j.d from json2_table order by ts; +-----------------------------------+ | json_get(json2_table.j,Utf8("d")) | +-----------------------------------+ -| [{e: {f: 0.1, g: }}] | -| [{e: {f: 0.2, g: }}] | +| [{"e":{"f":0.1,"g":null}}] | +| [{"e":{"f":0.2,"g":null}}] | | | -| [{e: {f: , g: -0.4}}] | +| [{"e":{"f":null,"g":-0.4}}] | | | | | -| [{e: {g: -0.7}}] | +| [{"e":{"g":-0.7}}] | | | -| [{e: {g: -0.9}}] | +| [{"e":{"g":-0.9}}] | | | +-----------------------------------+ @@ -234,6 +234,61 @@ drop table json2_table; Affected Rows: 0 +-- A JSON null in a dynamically typed field must remain SQL NULL when the +-- field is projected to the default string type, rather than becoming "null". +create table json2_variant_null ( + ts timestamp time index, + j json2 +) with ( + 'append_mode' = 'true', + 'sst_format' = 'flat' +); + +Affected Rows: 0 + +insert into json2_variant_null values + (1, '{"payload":{"value":1}}'), + (2, '{"payload":"text"}'), + (3, '{"payload":null}'); + +Affected Rows: 3 + +select ts, j.payload, j.payload is null as payload_is_null +from json2_variant_null +order by ts; + ++-------------------------+------------------------------------------------+-----------------+ +| ts | json_get(json2_variant_null.j,Utf8("payload")) | payload_is_null | ++-------------------------+------------------------------------------------+-----------------+ +| 1970-01-01T00:00:00.001 | {"value":1} | false | +| 1970-01-01T00:00:00.002 | text | false | +| 1970-01-01T00:00:00.003 | | true | ++-------------------------+------------------------------------------------+-----------------+ + +admin flush_table('json2_variant_null'); + ++-----------------------------------------+ +| ADMIN flush_table('json2_variant_null') | ++-----------------------------------------+ +| 0 | ++-----------------------------------------+ + +select ts, j.payload, j.payload is null as payload_is_null +from json2_variant_null +order by ts; + ++-------------------------+------------------------------------------------+-----------------+ +| ts | json_get(json2_variant_null.j,Utf8("payload")) | payload_is_null | ++-------------------------+------------------------------------------------+-----------------+ +| 1970-01-01T00:00:00.001 | {"value":1} | false | +| 1970-01-01T00:00:00.002 | text | false | +| 1970-01-01T00:00:00.003 | | true | ++-------------------------+------------------------------------------------+-----------------+ + +drop table json2_variant_null; + +Affected Rows: 0 + create table json2_without_append_mode ( ts timestamp time index, j json2 diff --git a/tests/cases/standalone/common/types/json/json2.sql b/tests/cases/standalone/common/types/json/json2.sql index 0f1c484cdd..39390bf592 100644 --- a/tests/cases/standalone/common/types/json/json2.sql +++ b/tests/cases/standalone/common/types/json/json2.sql @@ -73,6 +73,33 @@ select j.d from json2_table order by ts; drop table json2_table; +-- A JSON null in a dynamically typed field must remain SQL NULL when the +-- field is projected to the default string type, rather than becoming "null". +create table json2_variant_null ( + ts timestamp time index, + j json2 +) with ( + 'append_mode' = 'true', + 'sst_format' = 'flat' +); + +insert into json2_variant_null values + (1, '{"payload":{"value":1}}'), + (2, '{"payload":"text"}'), + (3, '{"payload":null}'); + +select ts, j.payload, j.payload is null as payload_is_null +from json2_variant_null +order by ts; + +admin flush_table('json2_variant_null'); + +select ts, j.payload, j.payload is null as payload_is_null +from json2_variant_null +order by ts; + +drop table json2_variant_null; + create table json2_without_append_mode ( ts timestamp time index, j json2 diff --git a/tests/cases/standalone/common/types/json/json2_deep_nesting.result b/tests/cases/standalone/common/types/json/json2_deep_nesting.result new file mode 100644 index 0000000000..1f91ac497d --- /dev/null +++ b/tests/cases/standalone/common/types/json/json2_deep_nesting.result @@ -0,0 +1,234 @@ +-- A 49-level value stays fully structured because it is below the limit. +create table json2_depth_49 ( + ts timestamp time index, + j json2 +) with ( + 'append_mode' = 'true', + 'sst_format' = 'flat' +); + +Affected Rows: 0 + +insert into json2_depth_49 values ( + 1, + '{"level_01":{"level_02":{"level_03":{"level_04":{"level_05":{"level_06":{"level_07":{"level_08":{"level_09":{"level_10":{"level_11":{"level_12":{"level_13":{"level_14":{"level_15":{"level_16":{"level_17":{"level_18":{"level_19":{"level_20":{"level_21":{"level_22":{"level_23":{"level_24":{"level_25":{"level_26":{"level_27":{"level_28":{"level_29":{"level_30":{"level_31":{"level_32":{"level_33":{"level_34":{"level_35":{"level_36":{"level_37":{"level_38":{"level_39":{"level_40":{"level_41":{"level_42":{"level_43":{"level_44":{"level_45":{"level_46":{"level_47":{"level_48":{"level_49":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}' +); + +Affected Rows: 1 + +select j.level_01 from json2_depth_49; + ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| json_get(json2_depth_49.j,Utf8("level_01")) | ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| {"level_02":{"level_03":{"level_04":{"level_05":{"level_06":{"level_07":{"level_08":{"level_09":{"level_10":{"level_11":{"level_12":{"level_13":{"level_14":{"level_15":{"level_16":{"level_17":{"level_18":{"level_19":{"level_20":{"level_21":{"level_22":{"level_23":{"level_24":{"level_25":{"level_26":{"level_27":{"level_28":{"level_29":{"level_30":{"level_31":{"level_32":{"level_33":{"level_34":{"level_35":{"level_36":{"level_37":{"level_38":{"level_39":{"level_40":{"level_41":{"level_42":{"level_43":{"level_44":{"level_45":{"level_46":{"level_47":{"level_48":{"level_49":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} | ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +admin flush_table('json2_depth_49'); + ++-------------------------------------+ +| ADMIN flush_table('json2_depth_49') | ++-------------------------------------+ +| 0 | ++-------------------------------------+ + +select j.level_01 from json2_depth_49; + ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| json_get(json2_depth_49.j,Utf8("level_01")) | ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| {"level_02":{"level_03":{"level_04":{"level_05":{"level_06":{"level_07":{"level_08":{"level_09":{"level_10":{"level_11":{"level_12":{"level_13":{"level_14":{"level_15":{"level_16":{"level_17":{"level_18":{"level_19":{"level_20":{"level_21":{"level_22":{"level_23":{"level_24":{"level_25":{"level_26":{"level_27":{"level_28":{"level_29":{"level_30":{"level_31":{"level_32":{"level_33":{"level_34":{"level_35":{"level_36":{"level_37":{"level_38":{"level_39":{"level_40":{"level_41":{"level_42":{"level_43":{"level_44":{"level_45":{"level_46":{"level_47":{"level_48":{"level_49":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} | ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +drop table json2_depth_49; + +Affected Rows: 0 + +-- A 50-level value with a scalar at the boundary stays fully structured. +create table json2_depth_50 ( + ts timestamp time index, + j json2 +) with ( + 'append_mode' = 'true', + 'sst_format' = 'flat' +); + +Affected Rows: 0 + +insert into json2_depth_50 values ( + 1, + '{"level_01":{"level_02":{"level_03":{"level_04":{"level_05":{"level_06":{"level_07":{"level_08":{"level_09":{"level_10":{"level_11":{"level_12":{"level_13":{"level_14":{"level_15":{"level_16":{"level_17":{"level_18":{"level_19":{"level_20":{"level_21":{"level_22":{"level_23":{"level_24":{"level_25":{"level_26":{"level_27":{"level_28":{"level_29":{"level_30":{"level_31":{"level_32":{"level_33":{"level_34":{"level_35":{"level_36":{"level_37":{"level_38":{"level_39":{"level_40":{"level_41":{"level_42":{"level_43":{"level_44":{"level_45":{"level_46":{"level_47":{"level_48":{"level_49":{"level_50":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}' +); + +Affected Rows: 1 + +select j.level_01 from json2_depth_50; + ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| json_get(json2_depth_50.j,Utf8("level_01")) | ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| {"level_02":{"level_03":{"level_04":{"level_05":{"level_06":{"level_07":{"level_08":{"level_09":{"level_10":{"level_11":{"level_12":{"level_13":{"level_14":{"level_15":{"level_16":{"level_17":{"level_18":{"level_19":{"level_20":{"level_21":{"level_22":{"level_23":{"level_24":{"level_25":{"level_26":{"level_27":{"level_28":{"level_29":{"level_30":{"level_31":{"level_32":{"level_33":{"level_34":{"level_35":{"level_36":{"level_37":{"level_38":{"level_39":{"level_40":{"level_41":{"level_42":{"level_43":{"level_44":{"level_45":{"level_46":{"level_47":{"level_48":{"level_49":{"level_50":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} | ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +admin flush_table('json2_depth_50'); + ++-------------------------------------+ +| ADMIN flush_table('json2_depth_50') | ++-------------------------------------+ +| 0 | ++-------------------------------------+ + +select j.level_01 from json2_depth_50; + ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| json_get(json2_depth_50.j,Utf8("level_01")) | ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| {"level_02":{"level_03":{"level_04":{"level_05":{"level_06":{"level_07":{"level_08":{"level_09":{"level_10":{"level_11":{"level_12":{"level_13":{"level_14":{"level_15":{"level_16":{"level_17":{"level_18":{"level_19":{"level_20":{"level_21":{"level_22":{"level_23":{"level_24":{"level_25":{"level_26":{"level_27":{"level_28":{"level_29":{"level_30":{"level_31":{"level_32":{"level_33":{"level_34":{"level_35":{"level_36":{"level_37":{"level_38":{"level_39":{"level_40":{"level_41":{"level_42":{"level_43":{"level_44":{"level_45":{"level_46":{"level_47":{"level_48":{"level_49":{"level_50":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} | ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +drop table json2_depth_50; + +Affected Rows: 0 + +-- At 51 levels, the object at level 50 becomes a JSONB Variant. +create table json2_depth_51 ( + ts timestamp time index, + j json2 +) with ( + 'append_mode' = 'true', + 'sst_format' = 'flat' +); + +Affected Rows: 0 + +insert into json2_depth_51 values ( + 1, + '{"level_01":{"level_02":{"level_03":{"level_04":{"level_05":{"level_06":{"level_07":{"level_08":{"level_09":{"level_10":{"level_11":{"level_12":{"level_13":{"level_14":{"level_15":{"level_16":{"level_17":{"level_18":{"level_19":{"level_20":{"level_21":{"level_22":{"level_23":{"level_24":{"level_25":{"level_26":{"level_27":{"level_28":{"level_29":{"level_30":{"level_31":{"level_32":{"level_33":{"level_34":{"level_35":{"level_36":{"level_37":{"level_38":{"level_39":{"level_40":{"level_41":{"level_42":{"level_43":{"level_44":{"level_45":{"level_46":{"level_47":{"level_48":{"level_49":{"level_50":{"level_51":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}' +); + +Affected Rows: 1 + +select j.level_01 from json2_depth_51; + ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| json_get(json2_depth_51.j,Utf8("level_01")) | ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| {"level_02":{"level_03":{"level_04":{"level_05":{"level_06":{"level_07":{"level_08":{"level_09":{"level_10":{"level_11":{"level_12":{"level_13":{"level_14":{"level_15":{"level_16":{"level_17":{"level_18":{"level_19":{"level_20":{"level_21":{"level_22":{"level_23":{"level_24":{"level_25":{"level_26":{"level_27":{"level_28":{"level_29":{"level_30":{"level_31":{"level_32":{"level_33":{"level_34":{"level_35":{"level_36":{"level_37":{"level_38":{"level_39":{"level_40":{"level_41":{"level_42":{"level_43":{"level_44":{"level_45":{"level_46":{"level_47":{"level_48":{"level_49":{"level_50":{"level_51":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} | ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +-- The capped JSONB object should still be readable as JSON, and its leaf should remain queryable. +select json_get(j, 'level_01.level_02.level_03.level_04.level_05.level_06.level_07.level_08.level_09.level_10.level_11.level_12.level_13.level_14.level_15.level_16.level_17.level_18.level_19.level_20.level_21.level_22.level_23.level_24.level_25.level_26.level_27.level_28.level_29.level_30.level_31.level_32.level_33.level_34.level_35.level_36.level_37.level_38.level_39.level_40.level_41.level_42.level_43.level_44.level_45.level_46.level_47.level_48.level_49.level_50') from json2_depth_51; + ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| json_get(json2_depth_51.j,Utf8("level_01.level_02.level_03.level_04.level_05.level_06.level_07.level_08.level_09.level_10.level_11.level_12.level_13.level_14.level_15.level_16.level_17.level_18.level_19.level_20.level_21.level_22.level_23.level_24.level_25.level_26.level_27.level_28.level_29.level_30.level_31.level_32.level_33.level_34.level_35.level_36.level_37.level_38.level_39.level_40.level_41.level_42.level_43.level_44.level_45.level_46.level_47.level_48.level_49.level_50")) | ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| {"level_51":1} | ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +select json_get(j, 'level_01.level_02.level_03.level_04.level_05.level_06.level_07.level_08.level_09.level_10.level_11.level_12.level_13.level_14.level_15.level_16.level_17.level_18.level_19.level_20.level_21.level_22.level_23.level_24.level_25.level_26.level_27.level_28.level_29.level_30.level_31.level_32.level_33.level_34.level_35.level_36.level_37.level_38.level_39.level_40.level_41.level_42.level_43.level_44.level_45.level_46.level_47.level_48.level_49.level_50.level_51')::int64 from json2_depth_51; + ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| arrow_cast(json_get(json2_depth_51.j,Utf8("level_01.level_02.level_03.level_04.level_05.level_06.level_07.level_08.level_09.level_10.level_11.level_12.level_13.level_14.level_15.level_16.level_17.level_18.level_19.level_20.level_21.level_22.level_23.level_24.level_25.level_26.level_27.level_28.level_29.level_30.level_31.level_32.level_33.level_34.level_35.level_36.level_37.level_38.level_39.level_40.level_41.level_42.level_43.level_44.level_45.level_46.level_47.level_48.level_49.level_50.level_51")),Utf8("Int64")) | ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 1 | ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +admin flush_table('json2_depth_51'); + ++-------------------------------------+ +| ADMIN flush_table('json2_depth_51') | ++-------------------------------------+ +| 0 | ++-------------------------------------+ + +select j.level_01 from json2_depth_51; + ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| json_get(json2_depth_51.j,Utf8("level_01")) | ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| {"level_02":{"level_03":{"level_04":{"level_05":{"level_06":{"level_07":{"level_08":{"level_09":{"level_10":{"level_11":{"level_12":{"level_13":{"level_14":{"level_15":{"level_16":{"level_17":{"level_18":{"level_19":{"level_20":{"level_21":{"level_22":{"level_23":{"level_24":{"level_25":{"level_26":{"level_27":{"level_28":{"level_29":{"level_30":{"level_31":{"level_32":{"level_33":{"level_34":{"level_35":{"level_36":{"level_37":{"level_38":{"level_39":{"level_40":{"level_41":{"level_42":{"level_43":{"level_44":{"level_45":{"level_46":{"level_47":{"level_48":{"level_49":{"level_50":{"level_51":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} | ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +select json_get(j, 'level_01.level_02.level_03.level_04.level_05.level_06.level_07.level_08.level_09.level_10.level_11.level_12.level_13.level_14.level_15.level_16.level_17.level_18.level_19.level_20.level_21.level_22.level_23.level_24.level_25.level_26.level_27.level_28.level_29.level_30.level_31.level_32.level_33.level_34.level_35.level_36.level_37.level_38.level_39.level_40.level_41.level_42.level_43.level_44.level_45.level_46.level_47.level_48.level_49.level_50') from json2_depth_51; + ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| json_get(json2_depth_51.j,Utf8("level_01.level_02.level_03.level_04.level_05.level_06.level_07.level_08.level_09.level_10.level_11.level_12.level_13.level_14.level_15.level_16.level_17.level_18.level_19.level_20.level_21.level_22.level_23.level_24.level_25.level_26.level_27.level_28.level_29.level_30.level_31.level_32.level_33.level_34.level_35.level_36.level_37.level_38.level_39.level_40.level_41.level_42.level_43.level_44.level_45.level_46.level_47.level_48.level_49.level_50")) | ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| {"level_51":1} | ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +select json_get(j, 'level_01.level_02.level_03.level_04.level_05.level_06.level_07.level_08.level_09.level_10.level_11.level_12.level_13.level_14.level_15.level_16.level_17.level_18.level_19.level_20.level_21.level_22.level_23.level_24.level_25.level_26.level_27.level_28.level_29.level_30.level_31.level_32.level_33.level_34.level_35.level_36.level_37.level_38.level_39.level_40.level_41.level_42.level_43.level_44.level_45.level_46.level_47.level_48.level_49.level_50.level_51')::int64 from json2_depth_51; + ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| arrow_cast(json_get(json2_depth_51.j,Utf8("level_01.level_02.level_03.level_04.level_05.level_06.level_07.level_08.level_09.level_10.level_11.level_12.level_13.level_14.level_15.level_16.level_17.level_18.level_19.level_20.level_21.level_22.level_23.level_24.level_25.level_26.level_27.level_28.level_29.level_30.level_31.level_32.level_33.level_34.level_35.level_36.level_37.level_38.level_39.level_40.level_41.level_42.level_43.level_44.level_45.level_46.level_47.level_48.level_49.level_50.level_51")),Utf8("Int64")) | ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 1 | ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +drop table json2_depth_51; + +Affected Rows: 0 + +-- A much deeper value is also capped at level 50 instead of growing the Arrow schema. +create table json2_depth_70 ( + ts timestamp time index, + j json2 +) with ( + 'append_mode' = 'true', + 'sst_format' = 'flat' +); + +Affected Rows: 0 + +insert into json2_depth_70 values ( + 1, + '{"level_01":{"level_02":{"level_03":{"level_04":{"level_05":{"level_06":{"level_07":{"level_08":{"level_09":{"level_10":{"level_11":{"level_12":{"level_13":{"level_14":{"level_15":{"level_16":{"level_17":{"level_18":{"level_19":{"level_20":{"level_21":{"level_22":{"level_23":{"level_24":{"level_25":{"level_26":{"level_27":{"level_28":{"level_29":{"level_30":{"level_31":{"level_32":{"level_33":{"level_34":{"level_35":{"level_36":{"level_37":{"level_38":{"level_39":{"level_40":{"level_41":{"level_42":{"level_43":{"level_44":{"level_45":{"level_46":{"level_47":{"level_48":{"level_49":{"level_50":{"level_51":{"level_52":{"level_53":{"level_54":{"level_55":{"level_56":{"level_57":{"level_58":{"level_59":{"level_60":{"level_61":{"level_62":{"level_63":{"level_64":{"level_65":{"level_66":{"level_67":{"level_68":{"level_69":{"level_70":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}' +); + +Affected Rows: 1 + +select j.level_01 from json2_depth_70; + ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| json_get(json2_depth_70.j,Utf8("level_01")) | ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| {"level_02":{"level_03":{"level_04":{"level_05":{"level_06":{"level_07":{"level_08":{"level_09":{"level_10":{"level_11":{"level_12":{"level_13":{"level_14":{"level_15":{"level_16":{"level_17":{"level_18":{"level_19":{"level_20":{"level_21":{"level_22":{"level_23":{"level_24":{"level_25":{"level_26":{"level_27":{"level_28":{"level_29":{"level_30":{"level_31":{"level_32":{"level_33":{"level_34":{"level_35":{"level_36":{"level_37":{"level_38":{"level_39":{"level_40":{"level_41":{"level_42":{"level_43":{"level_44":{"level_45":{"level_46":{"level_47":{"level_48":{"level_49":{"level_50":{"level_51":{"level_52":{"level_53":{"level_54":{"level_55":{"level_56":{"level_57":{"level_58":{"level_59":{"level_60":{"level_61":{"level_62":{"level_63":{"level_64":{"level_65":{"level_66":{"level_67":{"level_68":{"level_69":{"level_70":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} | ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +-- Paths beyond the cap should traverse the JSONB Variant to the deepest leaf. +select json_get(j, 'level_01.level_02.level_03.level_04.level_05.level_06.level_07.level_08.level_09.level_10.level_11.level_12.level_13.level_14.level_15.level_16.level_17.level_18.level_19.level_20.level_21.level_22.level_23.level_24.level_25.level_26.level_27.level_28.level_29.level_30.level_31.level_32.level_33.level_34.level_35.level_36.level_37.level_38.level_39.level_40.level_41.level_42.level_43.level_44.level_45.level_46.level_47.level_48.level_49.level_50.level_51.level_52.level_53.level_54.level_55.level_56.level_57.level_58.level_59.level_60.level_61.level_62.level_63.level_64.level_65.level_66.level_67.level_68.level_69.level_70')::int64 from json2_depth_70; + ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| arrow_cast(json_get(json2_depth_70.j,Utf8("level_01.level_02.level_03.level_04.level_05.level_06.level_07.level_08.level_09.level_10.level_11.level_12.level_13.level_14.level_15.level_16.level_17.level_18.level_19.level_20.level_21.level_22.level_23.level_24.level_25.level_26.level_27.level_28.level_29.level_30.level_31.level_32.level_33.level_34.level_35.level_36.level_37.level_38.level_39.level_40.level_41.level_42.level_43.level_44.level_45.level_46.level_47.level_48.level_49.level_50.level_51.level_52.level_53.level_54.level_55.level_56.level_57.level_58.level_59.level_60.level_61.level_62.level_63.level_64.level_65.level_66.level_67.level_68.level_69.level_70")),Utf8("Int64")) | ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 1 | ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +admin flush_table('json2_depth_70'); + ++-------------------------------------+ +| ADMIN flush_table('json2_depth_70') | ++-------------------------------------+ +| 0 | ++-------------------------------------+ + +select j.level_01 from json2_depth_70; + ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| json_get(json2_depth_70.j,Utf8("level_01")) | ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| {"level_02":{"level_03":{"level_04":{"level_05":{"level_06":{"level_07":{"level_08":{"level_09":{"level_10":{"level_11":{"level_12":{"level_13":{"level_14":{"level_15":{"level_16":{"level_17":{"level_18":{"level_19":{"level_20":{"level_21":{"level_22":{"level_23":{"level_24":{"level_25":{"level_26":{"level_27":{"level_28":{"level_29":{"level_30":{"level_31":{"level_32":{"level_33":{"level_34":{"level_35":{"level_36":{"level_37":{"level_38":{"level_39":{"level_40":{"level_41":{"level_42":{"level_43":{"level_44":{"level_45":{"level_46":{"level_47":{"level_48":{"level_49":{"level_50":{"level_51":{"level_52":{"level_53":{"level_54":{"level_55":{"level_56":{"level_57":{"level_58":{"level_59":{"level_60":{"level_61":{"level_62":{"level_63":{"level_64":{"level_65":{"level_66":{"level_67":{"level_68":{"level_69":{"level_70":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} | ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +select json_get(j, 'level_01.level_02.level_03.level_04.level_05.level_06.level_07.level_08.level_09.level_10.level_11.level_12.level_13.level_14.level_15.level_16.level_17.level_18.level_19.level_20.level_21.level_22.level_23.level_24.level_25.level_26.level_27.level_28.level_29.level_30.level_31.level_32.level_33.level_34.level_35.level_36.level_37.level_38.level_39.level_40.level_41.level_42.level_43.level_44.level_45.level_46.level_47.level_48.level_49.level_50.level_51.level_52.level_53.level_54.level_55.level_56.level_57.level_58.level_59.level_60.level_61.level_62.level_63.level_64.level_65.level_66.level_67.level_68.level_69.level_70')::int64 from json2_depth_70; + ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| arrow_cast(json_get(json2_depth_70.j,Utf8("level_01.level_02.level_03.level_04.level_05.level_06.level_07.level_08.level_09.level_10.level_11.level_12.level_13.level_14.level_15.level_16.level_17.level_18.level_19.level_20.level_21.level_22.level_23.level_24.level_25.level_26.level_27.level_28.level_29.level_30.level_31.level_32.level_33.level_34.level_35.level_36.level_37.level_38.level_39.level_40.level_41.level_42.level_43.level_44.level_45.level_46.level_47.level_48.level_49.level_50.level_51.level_52.level_53.level_54.level_55.level_56.level_57.level_58.level_59.level_60.level_61.level_62.level_63.level_64.level_65.level_66.level_67.level_68.level_69.level_70")),Utf8("Int64")) | ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 1 | ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +drop table json2_depth_70; + +Affected Rows: 0 + diff --git a/tests/cases/standalone/common/types/json/json2_deep_nesting.sql b/tests/cases/standalone/common/types/json/json2_deep_nesting.sql new file mode 100644 index 0000000000..9bb75423d2 --- /dev/null +++ b/tests/cases/standalone/common/types/json/json2_deep_nesting.sql @@ -0,0 +1,101 @@ +-- A 49-level value stays fully structured because it is below the limit. +create table json2_depth_49 ( + ts timestamp time index, + j json2 +) with ( + 'append_mode' = 'true', + 'sst_format' = 'flat' +); + +insert into json2_depth_49 values ( + 1, + '{"level_01":{"level_02":{"level_03":{"level_04":{"level_05":{"level_06":{"level_07":{"level_08":{"level_09":{"level_10":{"level_11":{"level_12":{"level_13":{"level_14":{"level_15":{"level_16":{"level_17":{"level_18":{"level_19":{"level_20":{"level_21":{"level_22":{"level_23":{"level_24":{"level_25":{"level_26":{"level_27":{"level_28":{"level_29":{"level_30":{"level_31":{"level_32":{"level_33":{"level_34":{"level_35":{"level_36":{"level_37":{"level_38":{"level_39":{"level_40":{"level_41":{"level_42":{"level_43":{"level_44":{"level_45":{"level_46":{"level_47":{"level_48":{"level_49":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}' +); + +select j.level_01 from json2_depth_49; + +admin flush_table('json2_depth_49'); + +select j.level_01 from json2_depth_49; + +drop table json2_depth_49; + +-- A 50-level value with a scalar at the boundary stays fully structured. +create table json2_depth_50 ( + ts timestamp time index, + j json2 +) with ( + 'append_mode' = 'true', + 'sst_format' = 'flat' +); + +insert into json2_depth_50 values ( + 1, + '{"level_01":{"level_02":{"level_03":{"level_04":{"level_05":{"level_06":{"level_07":{"level_08":{"level_09":{"level_10":{"level_11":{"level_12":{"level_13":{"level_14":{"level_15":{"level_16":{"level_17":{"level_18":{"level_19":{"level_20":{"level_21":{"level_22":{"level_23":{"level_24":{"level_25":{"level_26":{"level_27":{"level_28":{"level_29":{"level_30":{"level_31":{"level_32":{"level_33":{"level_34":{"level_35":{"level_36":{"level_37":{"level_38":{"level_39":{"level_40":{"level_41":{"level_42":{"level_43":{"level_44":{"level_45":{"level_46":{"level_47":{"level_48":{"level_49":{"level_50":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}' +); + +select j.level_01 from json2_depth_50; + +admin flush_table('json2_depth_50'); + +select j.level_01 from json2_depth_50; + +drop table json2_depth_50; + +-- At 51 levels, the object at level 50 becomes a JSONB Variant. +create table json2_depth_51 ( + ts timestamp time index, + j json2 +) with ( + 'append_mode' = 'true', + 'sst_format' = 'flat' +); + +insert into json2_depth_51 values ( + 1, + '{"level_01":{"level_02":{"level_03":{"level_04":{"level_05":{"level_06":{"level_07":{"level_08":{"level_09":{"level_10":{"level_11":{"level_12":{"level_13":{"level_14":{"level_15":{"level_16":{"level_17":{"level_18":{"level_19":{"level_20":{"level_21":{"level_22":{"level_23":{"level_24":{"level_25":{"level_26":{"level_27":{"level_28":{"level_29":{"level_30":{"level_31":{"level_32":{"level_33":{"level_34":{"level_35":{"level_36":{"level_37":{"level_38":{"level_39":{"level_40":{"level_41":{"level_42":{"level_43":{"level_44":{"level_45":{"level_46":{"level_47":{"level_48":{"level_49":{"level_50":{"level_51":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}' +); + +select j.level_01 from json2_depth_51; + +-- The capped JSONB object should still be readable as JSON, and its leaf should remain queryable. +select json_get(j, 'level_01.level_02.level_03.level_04.level_05.level_06.level_07.level_08.level_09.level_10.level_11.level_12.level_13.level_14.level_15.level_16.level_17.level_18.level_19.level_20.level_21.level_22.level_23.level_24.level_25.level_26.level_27.level_28.level_29.level_30.level_31.level_32.level_33.level_34.level_35.level_36.level_37.level_38.level_39.level_40.level_41.level_42.level_43.level_44.level_45.level_46.level_47.level_48.level_49.level_50') from json2_depth_51; + +select json_get(j, 'level_01.level_02.level_03.level_04.level_05.level_06.level_07.level_08.level_09.level_10.level_11.level_12.level_13.level_14.level_15.level_16.level_17.level_18.level_19.level_20.level_21.level_22.level_23.level_24.level_25.level_26.level_27.level_28.level_29.level_30.level_31.level_32.level_33.level_34.level_35.level_36.level_37.level_38.level_39.level_40.level_41.level_42.level_43.level_44.level_45.level_46.level_47.level_48.level_49.level_50.level_51')::int64 from json2_depth_51; + +admin flush_table('json2_depth_51'); + +select j.level_01 from json2_depth_51; + +select json_get(j, 'level_01.level_02.level_03.level_04.level_05.level_06.level_07.level_08.level_09.level_10.level_11.level_12.level_13.level_14.level_15.level_16.level_17.level_18.level_19.level_20.level_21.level_22.level_23.level_24.level_25.level_26.level_27.level_28.level_29.level_30.level_31.level_32.level_33.level_34.level_35.level_36.level_37.level_38.level_39.level_40.level_41.level_42.level_43.level_44.level_45.level_46.level_47.level_48.level_49.level_50') from json2_depth_51; + +select json_get(j, 'level_01.level_02.level_03.level_04.level_05.level_06.level_07.level_08.level_09.level_10.level_11.level_12.level_13.level_14.level_15.level_16.level_17.level_18.level_19.level_20.level_21.level_22.level_23.level_24.level_25.level_26.level_27.level_28.level_29.level_30.level_31.level_32.level_33.level_34.level_35.level_36.level_37.level_38.level_39.level_40.level_41.level_42.level_43.level_44.level_45.level_46.level_47.level_48.level_49.level_50.level_51')::int64 from json2_depth_51; + +drop table json2_depth_51; + +-- A much deeper value is also capped at level 50 instead of growing the Arrow schema. +create table json2_depth_70 ( + ts timestamp time index, + j json2 +) with ( + 'append_mode' = 'true', + 'sst_format' = 'flat' +); + +insert into json2_depth_70 values ( + 1, + '{"level_01":{"level_02":{"level_03":{"level_04":{"level_05":{"level_06":{"level_07":{"level_08":{"level_09":{"level_10":{"level_11":{"level_12":{"level_13":{"level_14":{"level_15":{"level_16":{"level_17":{"level_18":{"level_19":{"level_20":{"level_21":{"level_22":{"level_23":{"level_24":{"level_25":{"level_26":{"level_27":{"level_28":{"level_29":{"level_30":{"level_31":{"level_32":{"level_33":{"level_34":{"level_35":{"level_36":{"level_37":{"level_38":{"level_39":{"level_40":{"level_41":{"level_42":{"level_43":{"level_44":{"level_45":{"level_46":{"level_47":{"level_48":{"level_49":{"level_50":{"level_51":{"level_52":{"level_53":{"level_54":{"level_55":{"level_56":{"level_57":{"level_58":{"level_59":{"level_60":{"level_61":{"level_62":{"level_63":{"level_64":{"level_65":{"level_66":{"level_67":{"level_68":{"level_69":{"level_70":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}' +); + +select j.level_01 from json2_depth_70; + +-- Paths beyond the cap should traverse the JSONB Variant to the deepest leaf. +select json_get(j, 'level_01.level_02.level_03.level_04.level_05.level_06.level_07.level_08.level_09.level_10.level_11.level_12.level_13.level_14.level_15.level_16.level_17.level_18.level_19.level_20.level_21.level_22.level_23.level_24.level_25.level_26.level_27.level_28.level_29.level_30.level_31.level_32.level_33.level_34.level_35.level_36.level_37.level_38.level_39.level_40.level_41.level_42.level_43.level_44.level_45.level_46.level_47.level_48.level_49.level_50.level_51.level_52.level_53.level_54.level_55.level_56.level_57.level_58.level_59.level_60.level_61.level_62.level_63.level_64.level_65.level_66.level_67.level_68.level_69.level_70')::int64 from json2_depth_70; + +admin flush_table('json2_depth_70'); + +select j.level_01 from json2_depth_70; + +select json_get(j, 'level_01.level_02.level_03.level_04.level_05.level_06.level_07.level_08.level_09.level_10.level_11.level_12.level_13.level_14.level_15.level_16.level_17.level_18.level_19.level_20.level_21.level_22.level_23.level_24.level_25.level_26.level_27.level_28.level_29.level_30.level_31.level_32.level_33.level_34.level_35.level_36.level_37.level_38.level_39.level_40.level_41.level_42.level_43.level_44.level_45.level_46.level_47.level_48.level_49.level_50.level_51.level_52.level_53.level_54.level_55.level_56.level_57.level_58.level_59.level_60.level_61.level_62.level_63.level_64.level_65.level_66.level_67.level_68.level_69.level_70')::int64 from json2_depth_70; + +drop table json2_depth_70; diff --git a/tests/cases/standalone/common/types/json/json2_type_hints.result b/tests/cases/standalone/common/types/json/json2_type_hints.result index 45565c56fb..c79607f8f9 100644 --- a/tests/cases/standalone/common/types/json/json2_type_hints.result +++ b/tests/cases/standalone/common/types/json/json2_type_hints.result @@ -88,6 +88,30 @@ CREATE TABLE json2_type_hints_timestamp ( Error: 2000(InvalidSyntax), Invalid SQL, error: unsupported JSON2 type hint data type: TIMESTAMP +-- A type hint at the maximum supported depth is accepted. +CREATE TABLE json2_type_hint_depth_50 ( + ts TIMESTAMP TIME INDEX, + j JSON2 ( + l01.l02.l03.l04.l05.l06.l07.l08.l09.l10.l11.l12.l13.l14.l15.l16.l17.l18.l19.l20.l21.l22.l23.l24.l25.l26.l27.l28.l29.l30.l31.l32.l33.l34.l35.l36.l37.l38.l39.l40.l41.l42.l43.l44.l45.l46.l47.l48.l49.l50 STRING + ) +) WITH ( + 'append_mode' = 'true' +); + +Affected Rows: 0 + +-- A type hint beyond the structured depth limit is rejected at CREATE TABLE. +CREATE TABLE json2_type_hint_depth_51 ( + ts TIMESTAMP TIME INDEX, + j JSON2 ( + l01.l02.l03.l04.l05.l06.l07.l08.l09.l10.l11.l12.l13.l14.l15.l16.l17.l18.l19.l20.l21.l22.l23.l24.l25.l26.l27.l28.l29.l30.l31.l32.l33.l34.l35.l36.l37.l38.l39.l40.l41.l42.l43.l44.l45.l46.l47.l48.l49.l50.l51 STRING + ) +) WITH ( + 'append_mode' = 'true' +); + +Error: 2000(InvalidSyntax), Invalid SQL, error: JSON2 type hint path cannot exceed 50 segments + DROP TABLE json2_type_hints; Affected Rows: 0 @@ -96,3 +120,7 @@ DROP TABLE json2_type_hints_required; Affected Rows: 0 +DROP TABLE json2_type_hint_depth_50; + +Affected Rows: 0 + diff --git a/tests/cases/standalone/common/types/json/json2_type_hints.sql b/tests/cases/standalone/common/types/json/json2_type_hints.sql index 4d3e5a39d1..9cdd25295b 100644 --- a/tests/cases/standalone/common/types/json/json2_type_hints.sql +++ b/tests/cases/standalone/common/types/json/json2_type_hints.sql @@ -48,6 +48,28 @@ CREATE TABLE json2_type_hints_timestamp ( ) ); +-- A type hint at the maximum supported depth is accepted. +CREATE TABLE json2_type_hint_depth_50 ( + ts TIMESTAMP TIME INDEX, + j JSON2 ( + l01.l02.l03.l04.l05.l06.l07.l08.l09.l10.l11.l12.l13.l14.l15.l16.l17.l18.l19.l20.l21.l22.l23.l24.l25.l26.l27.l28.l29.l30.l31.l32.l33.l34.l35.l36.l37.l38.l39.l40.l41.l42.l43.l44.l45.l46.l47.l48.l49.l50 STRING + ) +) WITH ( + 'append_mode' = 'true' +); + +-- A type hint beyond the structured depth limit is rejected at CREATE TABLE. +CREATE TABLE json2_type_hint_depth_51 ( + ts TIMESTAMP TIME INDEX, + j JSON2 ( + l01.l02.l03.l04.l05.l06.l07.l08.l09.l10.l11.l12.l13.l14.l15.l16.l17.l18.l19.l20.l21.l22.l23.l24.l25.l26.l27.l28.l29.l30.l31.l32.l33.l34.l35.l36.l37.l38.l39.l40.l41.l42.l43.l44.l45.l46.l47.l48.l49.l50.l51 STRING + ) +) WITH ( + 'append_mode' = 'true' +); + DROP TABLE json2_type_hints; DROP TABLE json2_type_hints_required; + +DROP TABLE json2_type_hint_depth_50;