1use std::cmp::Ordering;
16use std::sync::Arc;
17
18use arrow::compute::{can_cast_types, cast};
19use arrow_array::cast::AsArray;
20use arrow_array::types::{
21 Float32Type, Float64Type, Int8Type, Int16Type, Int32Type, Int64Type, UInt8Type, UInt16Type,
22 UInt32Type, UInt64Type,
23};
24use arrow_array::{Array, ArrayRef, GenericListArray, ListArray, StructArray, new_null_array};
25use arrow_schema::{DataType, Field, FieldRef};
26use common_telemetry::trace;
27use serde_json::Value;
28use snafu::{OptionExt, ResultExt};
29
30use crate::arrow_array::{MutableBinaryArray, binary_array_value, string_array_value};
31use crate::data_type::ConcreteDataType;
32use crate::error::{
33 AlignJsonArraySnafu, ArrowComputeSnafu, InvalidJsonSnafu, InvalidJsonbSnafu, Result,
34};
35use crate::extension::json::{JSON2_REMAINDER_FIELD_NAME, json2_remainder_field};
36use crate::json::JsonSettings;
37use crate::json::value::{decode_json_variant, encode_serde_json_as_jsonb};
38use crate::prelude::{DataType as _, Value as GreptimeValue};
39use crate::value::{ListValue, StructValue};
40use crate::vectors::MutableVector;
41use crate::vectors::json::builder::{JsonVectorBuilder, json2_physical_data_type};
42use crate::vectors::json::variant::variant_to_json_values;
43
44pub struct JsonArray<'a> {
45 inner: &'a ArrayRef,
46}
47
48impl JsonArray<'_> {
49 pub fn try_get_value(&self, i: usize) -> Result<Value> {
51 let array = self.inner;
52 if array.is_null(i) {
53 return Ok(Value::Null);
54 }
55
56 let value = match array.data_type() {
57 DataType::Null => Value::Null,
58 DataType::Boolean => Value::Bool(array.as_boolean().value(i)),
59 DataType::Int8 => Value::from(array.as_primitive::<Int8Type>().value(i)),
60 DataType::Int16 => Value::from(array.as_primitive::<Int16Type>().value(i)),
61 DataType::Int32 => Value::from(array.as_primitive::<Int32Type>().value(i)),
62 DataType::Int64 => Value::from(array.as_primitive::<Int64Type>().value(i)),
63 DataType::UInt8 => Value::from(array.as_primitive::<UInt8Type>().value(i)),
64 DataType::UInt16 => Value::from(array.as_primitive::<UInt16Type>().value(i)),
65 DataType::UInt32 => Value::from(array.as_primitive::<UInt32Type>().value(i)),
66 DataType::UInt64 => Value::from(array.as_primitive::<UInt64Type>().value(i)),
67 DataType::Float32 => Value::from(array.as_primitive::<Float32Type>().value(i)),
68 DataType::Float64 => Value::from(array.as_primitive::<Float64Type>().value(i)),
69 DataType::Utf8 | DataType::LargeUtf8 | DataType::Utf8View => {
70 Value::String(string_array_value(array, i).to_string())
71 }
72 DataType::Binary | DataType::LargeBinary | DataType::BinaryView => {
73 let bytes = binary_array_value(array, i);
74 decode_json_variant(bytes).map_err(|error| InvalidJsonbSnafu { error }.build())?
75 }
76 DataType::Struct(_) => {
77 let structs = array.as_struct();
78 let object = structs
79 .fields()
80 .iter()
81 .zip(structs.columns())
82 .map(|(field, column)| {
83 JsonArray::from(column)
84 .try_get_value(i)
85 .map(|v| (field.name().clone(), v))
86 })
87 .collect::<Result<_>>()?;
88 Value::Object(object)
89 }
90 DataType::List(_) => {
91 let lists = array.as_list::<i32>();
92 let list = lists.value(i);
93 let list = JsonArray::from(&list);
94 let mut values = Vec::with_capacity(list.inner.len());
95 for i in 0..list.inner.len() {
96 values.push(list.try_get_value(i)?);
97 }
98 Value::Array(values)
99 }
100 t => {
101 return InvalidJsonSnafu {
102 value: format!("unknown JSON type {t}"),
103 }
104 .fail();
105 }
106 };
107 Ok(value)
108 }
109
110 pub fn project_to_v2(&self, field: &Field, target: &DataType) -> Result<ArrayRef> {
114 if json2_remainder_field(field)?.is_some() {
115 project_json_values(self.json2_values()?, target)
116 } else {
117 self.project_to(target)
118 }
119 }
120
121 pub fn rewrite_to_v2(
124 &self,
125 field: &Field,
126 logical_settings: &JsonSettings,
127 target_layout: &JsonSettings,
128 ) -> Result<ArrayRef> {
129 let is_v2 = json2_remainder_field(field)?.is_some();
130 if is_v2 && self.inner.data_type() == &json2_physical_data_type(target_layout) {
131 return Ok(self.inner.clone());
132 }
133
134 let values = if is_v2 {
135 self.json2_values()?
136 } else {
137 (0..self.inner.len())
138 .map(|i| self.try_get_value(i))
139 .collect::<Result<Vec<_>>>()?
140 };
141 let mut builder = JsonVectorBuilder::with_settings(target_layout, values.len());
142 for value in values {
143 if value.is_null() {
144 builder.push_null();
145 } else {
146 let value = logical_settings.encode(value)?;
147 builder.try_push_value_ref(&value.as_value_ref())?;
148 }
149 }
150 Ok(builder.to_vector().to_arrow_array())
151 }
152
153 fn json2_values(&self) -> Result<Vec<Value>> {
154 let structs = self.inner.as_struct_opt().context(AlignJsonArraySnafu {
155 reason: "JSON2 layout v2 root array must be a struct",
156 })?;
157 let remainder = structs.column_by_name(JSON2_REMAINDER_FIELD_NAME);
158 let mut remainders = if let Some(remainder) = remainder {
159 variant_to_json_values(remainder)?
160 } else {
161 vec![None; structs.len()]
162 };
163 let mut values = Vec::with_capacity(structs.len());
164 let mut path = Vec::new();
165
166 for (i, remainder) in remainders.iter_mut().enumerate() {
167 if structs.is_null(i) {
168 values.push(Value::Null);
169 continue;
170 }
171
172 let mut object = match remainder.take() {
173 None => serde_json::Map::new(),
174 Some(Value::Object(object)) => object,
175 Some(value) => {
176 return InvalidJsonSnafu {
177 value: format!("JSON2 layout v2 remainder must be an object, got {value}"),
178 }
179 .fail();
180 }
181 };
182
183 for (child, column) in structs.fields().iter().zip(structs.columns()) {
184 if child.name() == JSON2_REMAINDER_FIELD_NAME {
185 continue;
186 }
187 let mut value = JsonArray::from(column).try_get_value(i)?;
188 remove_null_object_fields(&mut value);
192 if value.is_null() {
193 continue;
194 }
195 merge_explicit_value(&mut object, child.name().clone(), value, &mut path)?;
196 }
197 values.push(Value::Object(object));
198 }
199
200 Ok(values)
201 }
202
203 pub fn widen_to(&self, expect: &DataType) -> Result<ArrayRef> {
214 let data_type = self.inner.data_type();
215
216 if data_type == expect {
217 return Ok(self.inner.clone());
218 }
219
220 trace!(
221 "Try aligning JSON array {} to data type {}",
222 data_type, expect
223 );
224
225 let struct_array = self.inner.as_struct_opt().context(AlignJsonArraySnafu {
226 reason: "expect struct array",
227 })?;
228 let array_fields = struct_array.fields();
229 let array_columns = struct_array.columns();
230 let DataType::Struct(expect_fields) = expect else {
231 return AlignJsonArraySnafu {
232 reason: "expect struct datatype",
233 }
234 .fail();
235 };
236 let mut aligned = Vec::with_capacity(expect_fields.len());
237
238 debug_assert!(expect_fields.iter().map(|f| f.name()).is_sorted());
243 debug_assert!(array_fields.iter().map(|f| f.name()).is_sorted());
244
245 let mut i = 0; let mut j = 0; while i < expect_fields.len() && j < array_fields.len() {
248 let expect_field = &expect_fields[i];
249 let array_field = &array_fields[j];
250 match expect_field.name().cmp(array_field.name()) {
251 Ordering::Equal => {
252 if expect_field.data_type() == array_field.data_type() {
253 aligned.push(array_columns[j].clone());
254 } else {
255 let expect_type = expect_field.data_type();
256 let array_type = array_field.data_type();
257 let array = match (expect_type, array_type) {
258 (DataType::Struct(_), DataType::Struct(_)) => {
259 JsonArray::from(&array_columns[j]).widen_to(expect_type)?
260 }
261 (DataType::List(expect_item), DataType::List(array_item)) => {
262 let list_array = array_columns[j].as_list::<i32>();
263 widen_list(list_array, array_item, expect_item)?
264 }
265 _ => JsonArray::from(&array_columns[j]).widen_scalar_to(expect_type)?,
266 };
267 aligned.push(array);
268 }
269 i += 1;
270 j += 1;
271 }
272 Ordering::Less => {
273 aligned.push(new_null_array(expect_field.data_type(), struct_array.len()));
274 i += 1;
275 }
276 Ordering::Greater => {
277 return AlignJsonArraySnafu {
278 reason: format!(
279 "source field {} does not exist in target schema",
280 array_field.name()
281 ),
282 }
283 .fail();
284 }
285 }
286 }
287 if j < array_fields.len() {
288 return AlignJsonArraySnafu {
289 reason: format!(
290 "source field {} does not exist in target schema",
291 array_fields[j].name()
292 ),
293 }
294 .fail();
295 }
296 if i < expect_fields.len() {
297 for field in &expect_fields[i..] {
298 aligned.push(new_null_array(field.data_type(), struct_array.len()));
299 }
300 }
301
302 let json_array = StructArray::try_new_with_length(
303 expect_fields.clone(),
304 aligned,
305 struct_array.nulls().cloned(),
306 struct_array.len(),
307 )
308 .map_err(|e| {
309 AlignJsonArraySnafu {
310 reason: e.to_string(),
311 }
312 .build()
313 })?;
314 Ok(Arc::new(json_array))
315 }
316
317 fn widen_scalar_to(&self, to_type: &DataType) -> Result<ArrayRef> {
326 let from_type = self.inner.data_type();
327 if from_type == to_type {
328 return Ok(self.inner.clone());
329 }
330
331 if from_type == &DataType::Null {
332 return Ok(new_null_array(to_type, self.inner.len()));
333 }
334
335 if !from_type.is_binary() && to_type.is_binary() {
336 return self.encode_variant();
337 }
338
339 AlignJsonArraySnafu {
340 reason: format!("unable to widen {from_type} to {to_type}"),
341 }
342 .fail()
343 }
344
345 fn encode_variant(&self) -> Result<ArrayRef> {
346 let len = self.inner.len();
347 let mut encoded = Vec::with_capacity(len);
348 let mut total_bytes = 0;
349
350 for i in 0..len {
351 let value = self.try_get_value(i)?;
352 if value.is_null() {
353 encoded.push(None);
354 } else {
355 let bytes = encode_serde_json_as_jsonb(value);
356 total_bytes += bytes.len();
357 encoded.push(Some(bytes));
358 }
359 }
360
361 let mut builder = MutableBinaryArray::with_capacity(len, total_bytes);
362 for value in encoded {
363 builder.append_option(value);
364 }
365 Ok(Arc::new(builder.finish()))
366 }
367
368 pub fn project_to(&self, target: &DataType) -> Result<ArrayRef> {
379 if self.inner.data_type() == target {
380 return Ok(self.inner.clone());
381 }
382
383 match (self.inner.data_type(), target) {
384 (DataType::Struct(_), DataType::Struct(target_fields)) => {
385 let struct_array = self.inner.as_struct();
386 let mut columns = Vec::with_capacity(target_fields.len());
387 for target_field in target_fields {
388 let column = struct_array
389 .column_by_name(target_field.name())
390 .map(|column| JsonArray::from(column).project_to(target_field.data_type()))
391 .transpose()?
392 .unwrap_or_else(|| {
393 new_null_array(target_field.data_type(), self.inner.len())
394 });
395 columns.push(column);
396 }
397 let projected = StructArray::try_new_with_length(
398 target_fields.clone(),
399 columns,
400 struct_array.nulls().cloned(),
401 struct_array.len(),
402 )
403 .context(ArrowComputeSnafu)?;
404 Ok(Arc::new(projected))
405 }
406 (DataType::List(_), DataType::List(target_item)) => {
407 let list_array = self.inner.as_list::<i32>();
408 let item_projected =
409 JsonArray::from(list_array.values()).project_to(target_item.data_type())?;
410 Ok(Arc::new(
411 GenericListArray::<i32>::try_new(
412 target_item.clone(),
413 list_array.offsets().clone(),
414 item_projected,
415 list_array.nulls().cloned(),
416 )
417 .context(ArrowComputeSnafu)?,
418 ))
419 }
420 _ => self.project_values_to(target),
421 }
422 }
423
424 fn project_values_to(&self, to_type: &DataType) -> Result<ArrayRef> {
425 let from_type = self.inner.data_type();
426 if can_fast_cast_types(from_type, to_type) {
427 return cast(self.inner.as_ref(), to_type).context(ArrowComputeSnafu);
428 }
429
430 let values = (0..self.inner.len())
431 .map(|i| self.try_get_value(i))
432 .collect::<Result<Vec<_>>>()?;
433 project_json_values(values, to_type)
434 }
435}
436
437fn merge_explicit_value(
438 remainder: &mut serde_json::Map<String, Value>,
439 key: String,
440 explicit: Value,
441 path: &mut Vec<String>,
442) -> Result<()> {
443 let Some(existing) = remainder.get_mut(&key) else {
444 remainder.insert(key, explicit);
445 return Ok(());
446 };
447 path.push(key);
448
449 let (Value::Object(remainder), Value::Object(explicit)) = (existing, explicit) else {
450 return InvalidJsonSnafu {
451 value: format!(
452 "cannot merge '{}' in explicit fields and remainder: not both objects",
453 path.join("."),
454 ),
455 }
456 .fail();
457 };
458 for (key, value) in explicit {
459 merge_explicit_value(remainder, key, value, path)?;
460 }
461 path.pop();
462 Ok(())
463}
464
465fn remove_null_object_fields(value: &mut Value) {
466 let Value::Object(object) = value else {
467 return;
468 };
469 object.retain(|_, value| {
470 remove_null_object_fields(value);
471 !value.is_null()
472 });
473}
474
475fn can_fast_cast_types(from_type: &DataType, to_type: &DataType) -> bool {
478 let is_scalar = |data_type: &DataType| {
479 data_type.is_numeric() || data_type.is_string() || data_type == &DataType::Boolean
480 };
481
482 is_scalar(from_type) && is_scalar(to_type) && can_cast_types(from_type, to_type)
483}
484
485fn project_json_values(values: Vec<Value>, to_type: &DataType) -> Result<ArrayRef> {
486 let concrete_type = ConcreteDataType::from_arrow_type(to_type);
487 let mut builder = concrete_type.create_mutable_vector(values.len());
488 for value in values {
489 let value = project_json_value_to_type(value, &concrete_type)?;
490 builder.try_push_value_ref(&value.as_value_ref())?;
491 }
492 Ok(builder.to_vector().to_arrow_array())
493}
494
495fn project_json_value_to_type(value: Value, to_type: &ConcreteDataType) -> Result<GreptimeValue> {
496 if value.is_null() {
497 return Ok(GreptimeValue::Null);
498 }
499
500 if to_type.is_string() {
501 let value = match value {
502 Value::String(value) => value,
503 value => value.to_string(),
504 };
505 return Ok(GreptimeValue::String(value.into()));
506 }
507
508 if matches!(to_type, ConcreteDataType::Binary(_)) {
509 return Ok(GreptimeValue::Binary(
510 encode_serde_json_as_jsonb(value).into(),
511 ));
512 }
513
514 if let Some(struct_type) = to_type.as_struct() {
515 let Value::Object(mut object) = value else {
516 return Ok(GreptimeValue::Null);
517 };
518 let values = struct_type
519 .fields()
520 .iter()
521 .map(|field| {
522 object
523 .remove(field.name())
524 .map(|value| project_json_value_to_type(value, field.data_type()))
525 .transpose()
526 .map(|value| value.unwrap_or(GreptimeValue::Null))
527 })
528 .collect::<Result<Vec<_>>>()?;
529 return Ok(GreptimeValue::Struct(StructValue::new(
530 values,
531 struct_type.clone(),
532 )));
533 }
534
535 if let Some(list_type) = to_type.as_list() {
536 let Value::Array(values) = value else {
537 return Ok(GreptimeValue::Null);
538 };
539 let item_type = list_type.item_type().clone();
540 let values = values
541 .into_iter()
542 .map(|value| project_json_value_to_type(value, &item_type))
543 .collect::<Result<Vec<_>>>()?;
544 return Ok(GreptimeValue::List(ListValue::new(
545 values,
546 Arc::new(item_type),
547 )));
548 }
549
550 let value = match value {
551 Value::Bool(value) => GreptimeValue::Boolean(value),
552 Value::Number(value) => {
553 if let Some(value) = value.as_i64() {
554 GreptimeValue::Int64(value)
555 } else if let Some(value) = value.as_u64() {
556 GreptimeValue::UInt64(value)
557 } else if let Some(value) = value.as_f64() {
558 GreptimeValue::Float64(value.into())
559 } else {
560 GreptimeValue::Null
561 }
562 }
563 Value::String(value) => GreptimeValue::String(value.into()),
564 Value::Array(_) | Value::Object(_) => GreptimeValue::Null,
565 Value::Null => GreptimeValue::Null,
566 };
567 Ok(to_type.try_cast(value).unwrap_or(GreptimeValue::Null))
568}
569
570fn widen_list(list_array: &ListArray, actual: &FieldRef, expected: &FieldRef) -> Result<ArrayRef> {
571 let item_aligned = match (actual.data_type(), expected.data_type()) {
572 (DataType::Struct(_), DataType::Struct(_)) => {
573 JsonArray::from(list_array.values()).widen_to(expected.data_type())?
574 }
575 (DataType::List(actual), DataType::List(expected)) => {
576 let list_array = list_array.values().as_list::<i32>();
577 widen_list(list_array, actual, expected)?
578 }
579 _ => JsonArray::from(list_array.values()).widen_scalar_to(expected.data_type())?,
580 };
581 Ok(Arc::new(
582 GenericListArray::<i32>::try_new(
583 expected.clone(),
584 list_array.offsets().clone(),
585 item_aligned,
586 list_array.nulls().cloned(),
587 )
588 .context(ArrowComputeSnafu)?,
589 ))
590}
591
592impl<'a> From<&'a ArrayRef> for JsonArray<'a> {
593 fn from(inner: &'a ArrayRef) -> Self {
594 Self { inner }
595 }
596}
597
598#[cfg(test)]
599mod test {
600 use std::sync::Arc;
601
602 use arrow_array::types::Int64Type;
603 use arrow_array::{
604 BinaryArray, BooleanArray, Float32Array, Float64Array, Int8Array, Int16Array, Int32Array,
605 Int64Array, ListArray, StringArray, UInt8Array, UInt16Array, UInt32Array, UInt64Array,
606 };
607 use arrow_schema::{Field, Fields};
608 use serde_json::json;
609
610 use super::*;
611 use crate::extension::json::{Json2ExtensionType, JsonMetadata};
612 use crate::json::{JsonSettings, JsonTypeHint};
613 use crate::vectors::json::variant::{json_values_to_variant, variant_field};
614
615 #[test]
616 fn test_try_get_value() -> Result<()> {
617 let nulls = new_null_array(&DataType::Null, 2);
618 assert_eq!(JsonArray::from(&nulls).try_get_value(0)?, Value::Null);
619
620 let bools: ArrayRef = Arc::new(BooleanArray::from(vec![Some(true), None]));
621 assert_eq!(JsonArray::from(&bools).try_get_value(0)?, json!(true));
622 assert_eq!(JsonArray::from(&bools).try_get_value(1)?, Value::Null);
623
624 let ints: ArrayRef = Arc::new(Int64Array::from(vec![Some(-7), None]));
625 assert_eq!(JsonArray::from(&ints).try_get_value(0)?, json!(-7));
626 assert_eq!(JsonArray::from(&ints).try_get_value(1)?, Value::Null);
627
628 macro_rules! assert_number {
629 ($array:expr, $expected:expr) => {{
630 let array: ArrayRef = Arc::new($array);
631 assert_eq!(JsonArray::from(&array).try_get_value(0)?, json!($expected));
632 }};
633 }
634 assert_number!(Int8Array::from(vec![-8]), -8);
635 assert_number!(Int16Array::from(vec![-16]), -16);
636 assert_number!(Int32Array::from(vec![-32]), -32);
637 assert_number!(UInt8Array::from(vec![8]), 8);
638 assert_number!(UInt16Array::from(vec![16]), 16);
639 assert_number!(UInt32Array::from(vec![32]), 32);
640 assert_number!(Float32Array::from(vec![1.25]), 1.25);
641
642 let floats: ArrayRef = Arc::new(Float64Array::from(vec![Some(1.5)]));
643 assert_eq!(JsonArray::from(&floats).try_get_value(0)?, json!(1.5));
644
645 let strings: ArrayRef = Arc::new(StringArray::from(vec![Some("hello"), None]));
646 assert_eq!(JsonArray::from(&strings).try_get_value(0)?, json!("hello"));
647 assert_eq!(JsonArray::from(&strings).try_get_value(1)?, Value::Null);
648
649 let nested = jsonb::parse_value(br#"{"nested":[1,null,"x"]}"#)
650 .unwrap()
651 .to_vec();
652 let null = jsonb::parse_value(b"null").unwrap().to_vec();
653 let binaries: ArrayRef =
654 Arc::new(BinaryArray::from(vec![nested.as_slice(), null.as_slice()]));
655 assert_eq!(
656 JsonArray::from(&binaries).try_get_value(0)?,
657 json!({"nested": [1, null, "x"]})
658 );
659 assert_eq!(JsonArray::from(&binaries).try_get_value(1)?, Value::Null);
660
661 let lists: ArrayRef = Arc::new(ListArray::from_iter_primitive::<Int64Type, _, _>(vec![
662 Some(vec![Some(1), None, Some(3)]),
663 None,
664 ]));
665 assert_eq!(
666 JsonArray::from(&lists).try_get_value(0)?,
667 json!([1, null, 3])
668 );
669 assert_eq!(JsonArray::from(&lists).try_get_value(1)?, Value::Null);
670
671 let structs: ArrayRef = Arc::new(StructArray::from(vec![
672 (
673 Arc::new(Field::new("flag", DataType::Boolean, true)),
674 Arc::new(BooleanArray::from(vec![Some(true), None])) as ArrayRef,
675 ),
676 (
677 Arc::new(Field::new_list(
678 "items",
679 Field::new_list_field(DataType::Int64, true),
680 true,
681 )),
682 Arc::new(ListArray::from_iter_primitive::<Int64Type, _, _>(vec![
683 Some(vec![Some(1), None]),
684 Some(vec![Some(2)]),
685 ])) as ArrayRef,
686 ),
687 ]));
688 assert_eq!(
689 JsonArray::from(&structs).try_get_value(0)?,
690 json!({"flag": true, "items": [1, null]})
691 );
692 assert_eq!(
693 JsonArray::from(&structs).try_get_value(1)?,
694 json!({"flag": null, "items": [2]})
695 );
696
697 Ok(())
698 }
699
700 #[test]
701 fn test_cast_variant_to_utf8_view_preserves_json_null() -> Result<()> {
702 let encode = |json: &[u8]| jsonb::parse_value(json).unwrap().to_vec();
703 let json_null = encode(b"null");
704 let object = encode(br#"{"value":1}"#);
705 let string = encode(br#""text""#);
706 let variants: ArrayRef = Arc::new(BinaryArray::from(vec![
707 Some(json_null.as_slice()),
708 Some(object.as_slice()),
709 Some(string.as_slice()),
710 None,
711 ]));
712
713 let casted = JsonArray::from(&variants).project_to(&DataType::Utf8View)?;
714 let casted = casted.as_string_view();
715 assert!(casted.is_null(0));
716 assert_eq!(casted.value(1), r#"{"value":1}"#);
717 assert_eq!(casted.value(2), "text");
718 assert!(casted.is_null(3));
719
720 Ok(())
721 }
722
723 #[test]
724 fn test_project_plain_scalars() -> Result<()> {
725 let integers: ArrayRef = Arc::new(Int64Array::from(vec![Some(42), Some(i64::MAX), None]));
726 let projected = JsonArray::from(&integers).project_to(&DataType::Int32)?;
727 let expected: ArrayRef = Arc::new(Int32Array::from(vec![Some(42), None, None]));
728 assert_eq!(&expected, &projected);
729
730 let booleans: ArrayRef = Arc::new(BooleanArray::from(vec![Some(true), Some(false), None]));
731 let projected = JsonArray::from(&booleans).project_to(&DataType::Float64)?;
732 let expected: ArrayRef = Arc::new(Float64Array::from(vec![Some(1.0), Some(0.0), None]));
733 assert_eq!(&expected, &projected);
734
735 let strings: ArrayRef = Arc::new(StringArray::from(vec![Some("42"), Some("bad"), None]));
736 let projected = JsonArray::from(&strings).project_to(&DataType::UInt64)?;
737 let expected: ArrayRef = Arc::new(UInt64Array::from(vec![Some(42), None, None]));
738 assert_eq!(&expected, &projected);
739
740 Ok(())
741 }
742
743 #[test]
744 fn test_widen_null_to_any_type() -> Result<()> {
745 let nulls = new_null_array(&DataType::Null, 2);
746 let target_types = [
747 DataType::Boolean,
748 DataType::UInt64,
749 DataType::Utf8View,
750 DataType::Binary,
751 DataType::List(Arc::new(Field::new_list_field(DataType::Int64, true))),
752 DataType::Struct(Fields::from(vec![Field::new(
753 "value",
754 DataType::Int64,
755 true,
756 )])),
757 ];
758
759 for target_type in target_types {
760 let widened = JsonArray::from(&nulls).widen_scalar_to(&target_type)?;
761 assert_eq!(&target_type, widened.data_type());
762 assert_eq!(2, widened.len());
763 assert_eq!(2, widened.null_count());
764 }
765
766 Ok(())
767 }
768
769 #[test]
770 fn test_widen_non_null_to_utf8_view_fails() {
771 let bools: ArrayRef = Arc::new(BooleanArray::from(vec![true]));
772 let err = JsonArray::from(&bools)
773 .widen_scalar_to(&DataType::Utf8View)
774 .unwrap_err();
775
776 assert_eq!(
777 "Failed to align JSON array, reason: unable to widen Boolean to Utf8View",
778 err.to_string()
779 );
780 }
781
782 #[test]
783 fn test_widen_variant_to_non_binary_fails() {
784 let value = jsonb::parse_value(b"true").unwrap().to_vec();
785 let variants: ArrayRef = Arc::new(BinaryArray::from(vec![value.as_slice()]));
786 let err = JsonArray::from(&variants)
787 .widen_scalar_to(&DataType::Boolean)
788 .unwrap_err();
789
790 assert_eq!(
791 "Failed to align JSON array, reason: unable to widen Binary to Boolean",
792 err.to_string()
793 );
794 }
795
796 #[test]
797 fn test_widen_between_number_types_fails() {
798 let values: ArrayRef = Arc::new(UInt64Array::from(vec![1]));
799 let err = JsonArray::from(&values)
800 .widen_scalar_to(&DataType::Int64)
801 .unwrap_err();
802
803 assert_eq!(
804 "Failed to align JSON array, reason: unable to widen UInt64 to Int64",
805 err.to_string()
806 );
807 }
808
809 #[test]
810 fn test_widen_numbers_to_variant_preserves_values() -> Result<()> {
811 let cases: [(ArrayRef, Value); 3] = [
812 (Arc::new(UInt64Array::from(vec![u64::MAX])), json!(u64::MAX)),
813 (Arc::new(Int64Array::from(vec![i64::MIN])), json!(i64::MIN)),
814 (Arc::new(Float64Array::from(vec![1.25])), json!(1.25)),
815 ];
816
817 for (values, expected) in cases {
818 let widened = JsonArray::from(&values).widen_scalar_to(&DataType::Binary)?;
819 assert_eq!(&DataType::Binary, widened.data_type());
820 assert_eq!(expected, JsonArray::from(&widened).try_get_value(0)?);
821 }
822
823 Ok(())
824 }
825
826 #[test]
827 fn test_align_json_array() -> Result<()> {
828 struct TestCase {
829 json_array: ArrayRef,
830 schema_type: DataType,
831 expected: std::result::Result<ArrayRef, String>,
832 }
833
834 impl TestCase {
835 fn new(
836 json_array: StructArray,
837 schema_type: Fields,
838 expected: std::result::Result<Vec<ArrayRef>, String>,
839 ) -> Self {
840 Self {
841 json_array: Arc::new(json_array),
842 schema_type: DataType::Struct(schema_type.clone()),
843 expected: expected
844 .map(|x| Arc::new(StructArray::new(schema_type, x, None)) as ArrayRef),
845 }
846 }
847
848 fn test(self) -> Result<()> {
849 let result = JsonArray::from(&self.json_array).widen_to(&self.schema_type);
850 match (result, self.expected) {
851 (Ok(json_array), Ok(expected)) => assert_eq!(&json_array, &expected),
852 (Ok(json_array), Err(e)) => {
853 panic!("expecting error {e} but actually get: {json_array:?}")
854 }
855 (Err(e), Err(expected)) => assert_eq!(e.to_string(), expected),
856 (Err(e), Ok(_)) => return Err(e),
857 }
858 Ok(())
859 }
860 }
861
862 TestCase::new(
864 StructArray::new_empty_fields(2, None),
865 Fields::from(vec![
866 Field::new("int", DataType::Int64, true),
867 Field::new_struct(
868 "nested",
869 vec![Field::new("bool", DataType::Boolean, true)],
870 true,
871 ),
872 Field::new("string", DataType::Utf8, true),
873 ]),
874 Ok(vec![
875 Arc::new(Int64Array::new_null(2)) as ArrayRef,
876 Arc::new(StructArray::new_null(
877 Fields::from(vec![Arc::new(Field::new("bool", DataType::Boolean, true))]),
878 2,
879 )),
880 Arc::new(StringArray::new_null(2)),
881 ]),
882 )
883 .test()?;
884
885 TestCase::new(
887 StructArray::from(vec![(
888 Arc::new(Field::new("float", DataType::Float64, true)),
889 Arc::new(Float64Array::from(vec![1.0, 2.0, 3.0])) as ArrayRef,
890 )]),
891 Fields::from(vec![
892 Field::new("float", DataType::Float64, true),
893 Field::new("string", DataType::Utf8, true),
894 ]),
895 Ok(vec![
896 Arc::new(Float64Array::from(vec![1.0, 2.0, 3.0])) as ArrayRef,
897 Arc::new(StringArray::new_null(3)),
898 ]),
899 )
900 .test()?;
901
902 TestCase::new(
904 StructArray::from(vec![
905 (
906 Arc::new(Field::new_list(
907 "list",
908 Field::new_list_field(DataType::Int64, true),
909 true,
910 )),
911 Arc::new(ListArray::from_iter_primitive::<Int64Type, _, _>(vec![
912 Some(vec![Some(1)]),
913 None,
914 Some(vec![Some(2), Some(3)]),
915 ])) as ArrayRef,
916 ),
917 (
918 Arc::new(Field::new_struct(
919 "nested",
920 vec![Field::new("int", DataType::Int64, true)],
921 true,
922 )),
923 Arc::new(StructArray::from(vec![(
924 Arc::new(Field::new("int", DataType::Int64, true)),
925 Arc::new(Int64Array::from(vec![-1, -2, -3])) as ArrayRef,
926 )])),
927 ),
928 (
929 Arc::new(Field::new("string", DataType::Utf8, true)),
930 Arc::new(StringArray::from(vec!["a", "b", "c"])),
931 ),
932 ]),
933 Fields::from(vec![
934 Field::new("bool", DataType::Boolean, true),
935 Field::new_list("list", Field::new_list_field(DataType::Int64, true), true),
936 Field::new_struct(
937 "nested",
938 vec![
939 Field::new("float", DataType::Float64, true),
940 Field::new("int", DataType::Int64, true),
941 ],
942 true,
943 ),
944 Field::new("string", DataType::Utf8, true),
945 ]),
946 Ok(vec![
947 Arc::new(BooleanArray::new_null(3)) as ArrayRef,
948 Arc::new(ListArray::from_iter_primitive::<Int64Type, _, _>(vec![
949 Some(vec![Some(1)]),
950 None,
951 Some(vec![Some(2), Some(3)]),
952 ])),
953 Arc::new(StructArray::from(vec![
954 (
955 Arc::new(Field::new("float", DataType::Float64, true)),
956 Arc::new(Float64Array::new_null(3)) as ArrayRef,
957 ),
958 (
959 Arc::new(Field::new("int", DataType::Int64, true)),
960 Arc::new(Int64Array::from(vec![-1, -2, -3])),
961 ),
962 ])),
963 Arc::new(StringArray::from(vec!["a", "b", "c"])),
964 ]),
965 )
966 .test()?;
967
968 TestCase::new(
970 StructArray::from(vec![(
971 Arc::new(Field::new("a", DataType::Boolean, true)),
972 Arc::new(BooleanArray::from(vec![true])) as ArrayRef,
973 )]),
974 Fields::from(vec![Field::new("b", DataType::Boolean, true)]),
975 Err(
976 "Failed to align JSON array, reason: source field a does not exist in target schema"
977 .to_string(),
978 ),
979 )
980 .test()?;
981
982 TestCase::new(
984 StructArray::from(vec![(
985 Arc::new(Field::new("b", DataType::Boolean, true)),
986 Arc::new(BooleanArray::from(vec![true])) as ArrayRef,
987 )]),
988 Fields::from(vec![Field::new("a", DataType::Boolean, true)]),
989 Err(
990 "Failed to align JSON array, reason: source field b does not exist in target schema"
991 .to_string(),
992 ),
993 )
994 .test()?;
995
996 Ok(())
997 }
998
999 #[test]
1000 fn test_align_variant_to_struct() -> Result<()> {
1001 let encode = |json: &[u8]| jsonb::parse_value(json).unwrap().to_vec();
1002 let object =
1003 encode(br#"{"nested":{"flag":true,"items":[1,2],"raw":{"x":1},"text":42,"value":42}}"#);
1004 let scalar = encode(b"1");
1005 let variants: ArrayRef = Arc::new(BinaryArray::from(vec![
1006 Some(object.as_slice()),
1007 None,
1008 Some(scalar.as_slice()),
1009 ]));
1010 let expected_type = DataType::Struct(Fields::from(vec![Field::new_struct(
1011 "nested",
1012 vec![
1013 Field::new("flag", DataType::Boolean, true),
1014 Field::new_list("items", Field::new_list_field(DataType::UInt64, true), true),
1015 Field::new("raw", DataType::Binary, true),
1016 Field::new("text", DataType::Utf8View, true),
1017 Field::new("value", DataType::UInt64, true),
1018 ],
1019 true,
1020 )]));
1021
1022 let aligned = JsonArray::from(&variants).project_to(&expected_type)?;
1023 assert_eq!(&expected_type, aligned.data_type());
1024 assert_eq!(
1025 json!({
1026 "nested": {
1027 "flag": true,
1028 "items": [1, 2],
1029 "raw": {"x": 1},
1030 "text": "42",
1031 "value": 42
1032 }
1033 }),
1034 JsonArray::from(&aligned).try_get_value(0)?
1035 );
1036 assert!(aligned.is_null(1));
1037 assert!(aligned.is_null(2));
1038
1039 Ok(())
1040 }
1041
1042 #[test]
1043 fn test_align_nested_variant_to_struct() -> Result<()> {
1044 let object = jsonb::parse_value(br#"{"flag":true,"value":42}"#)
1045 .unwrap()
1046 .to_vec();
1047 let variants: ArrayRef = Arc::new(BinaryArray::from(vec![Some(object.as_slice()), None]));
1048 let input: ArrayRef = Arc::new(StructArray::from(vec![(
1049 Arc::new(Field::new("nested", DataType::Binary, true)),
1050 variants,
1051 )]));
1052 let expected_type = DataType::Struct(Fields::from(vec![Field::new_struct(
1053 "nested",
1054 vec![
1055 Field::new("flag", DataType::Boolean, true),
1056 Field::new("value", DataType::UInt64, true),
1057 ],
1058 true,
1059 )]));
1060
1061 let aligned = JsonArray::from(&input).project_to(&expected_type)?;
1062 assert_eq!(&expected_type, aligned.data_type());
1063 assert_eq!(
1064 json!({"nested": {"flag": true, "value": 42}}),
1065 JsonArray::from(&aligned).try_get_value(0)?
1066 );
1067 assert_eq!(
1068 json!({"nested": null}),
1069 JsonArray::from(&aligned).try_get_value(1)?
1070 );
1071
1072 Ok(())
1073 }
1074
1075 #[test]
1076 fn test_reconstruct_json2_v2_value() -> Result<()> {
1077 let remainders = json_values_to_variant(&[
1078 Some(json!({"cold": 1, "nested": {"right": true}})),
1079 Some(json!({"!__remainder__!": "user value"})),
1080 ])?;
1081 let remainder = Arc::new(variant_field(JSON2_REMAINDER_FIELD_NAME, true));
1082 let nested = Arc::new(Field::new_struct(
1083 "nested",
1084 [Arc::new(Field::new("left", DataType::Utf8, true))],
1085 true,
1086 ));
1087 let nested_values: ArrayRef = Arc::new(StructArray::from(vec![(
1088 Arc::new(Field::new("left", DataType::Utf8, true)),
1089 Arc::new(StringArray::from(vec![Some("value"), None])) as ArrayRef,
1090 )]));
1091 let fields = Fields::from(vec![
1092 remainder,
1093 Arc::new(Field::new("count", DataType::Int64, true)),
1094 nested,
1095 ]);
1096 let array: ArrayRef = Arc::new(StructArray::new(
1097 fields.clone(),
1098 vec![
1099 remainders,
1100 Arc::new(Int64Array::from(vec![Some(42), None])),
1101 nested_values,
1102 ],
1103 None,
1104 ));
1105 let field = Field::new("data", DataType::Struct(fields), true).with_extension_type(
1106 Json2ExtensionType::new(Arc::new(JsonMetadata::new(JsonSettings::default()))),
1107 );
1108
1109 assert_eq!(
1110 json!({
1111 "cold": 1,
1112 "count": 42,
1113 "nested": {"left": "value", "right": true}
1114 }),
1115 JsonArray::from(&array).json2_values()?[0]
1116 );
1117 assert_eq!(
1118 json!({
1119 "!__remainder__!": "user value",
1120 "nested": {}
1121 }),
1122 JsonArray::from(&array).json2_values()?[1]
1123 );
1124 let target = DataType::Struct(
1125 vec![
1126 Arc::new(Field::new("cold", DataType::UInt64, true)),
1127 Arc::new(Field::new("count", DataType::Int64, true)),
1128 ]
1129 .into(),
1130 );
1131 let projected = JsonArray::from(&array).project_to_v2(&field, &target)?;
1132 assert_eq!(
1133 json!({"cold": 1, "count": 42}),
1134 JsonArray::from(&projected).try_get_value(0)?
1135 );
1136 assert_eq!(
1137 json!({"cold": null, "count": null}),
1138 JsonArray::from(&projected).try_get_value(1)?
1139 );
1140 Ok(())
1141 }
1142
1143 #[test]
1144 fn test_rewrite_to_v2_reuses_matching_layout() -> Result<()> {
1145 let settings = JsonSettings::try_new(
1146 vec![JsonTypeHint {
1147 path: vec!["kind".to_string()],
1148 data_type: ConcreteDataType::string_datatype(),
1149 nullable: true,
1150 default_constraint: None,
1151 inverted_index: false,
1152 }],
1153 Some(0),
1154 )?;
1155 let value = settings.encode(json!({"kind": "access", "cold": 1}))?;
1156 let mut builder = JsonVectorBuilder::with_settings(&settings, 1);
1157 builder.try_push_value_ref(&value.as_value_ref())?;
1158 let array = builder.to_vector().to_arrow_array();
1159 let structs = array.as_struct();
1160 assert!(structs.column_by_name("kind").is_some());
1161 assert_eq!(
1162 vec![Some(json!({"cold": 1}))],
1163 variant_to_json_values(structs.column_by_name(JSON2_REMAINDER_FIELD_NAME).unwrap())?
1164 );
1165 let field = Field::new("data", array.data_type().clone(), true).with_extension_type(
1166 Json2ExtensionType::new(Arc::new(JsonMetadata::new(settings.clone()))),
1167 );
1168
1169 let rewritten = JsonArray::from(&array).rewrite_to_v2(&field, &settings, &settings)?;
1170
1171 assert!(Arc::ptr_eq(&array, &rewritten));
1172 Ok(())
1173 }
1174
1175 #[test]
1176 fn test_project_partial_json2_v2_without_remainder() -> Result<()> {
1177 let fields = Fields::from(vec![Arc::new(Field::new("hot", DataType::Int64, true))]);
1178 let array: ArrayRef = Arc::new(StructArray::new(
1179 fields.clone(),
1180 vec![Arc::new(Int64Array::from(vec![1, 2]))],
1181 None,
1182 ));
1183 let field = Field::new("data", DataType::Struct(fields), true).with_extension_type(
1184 Json2ExtensionType::new(Arc::new(JsonMetadata::new(JsonSettings::default()))),
1185 );
1186
1187 let projected = JsonArray::from(&array).project_to_v2(&field, field.data_type())?;
1188 assert!(Arc::ptr_eq(&array, &projected));
1189 Ok(())
1190 }
1191
1192 #[test]
1193 fn test_reject_conflict_json2_v2_path() -> Result<()> {
1194 let remainders = json_values_to_variant(&[Some(json!({"count": 1}))])?;
1195 let fields = Fields::from(vec![
1196 Arc::new(variant_field(JSON2_REMAINDER_FIELD_NAME, true)),
1197 Arc::new(Field::new("count", DataType::Int64, true)),
1198 ]);
1199 let array: ArrayRef = Arc::new(StructArray::new(
1200 fields,
1201 vec![remainders, Arc::new(Int64Array::from(vec![2]))],
1202 None,
1203 ));
1204 let error = JsonArray::from(&array).json2_values().unwrap_err();
1205 assert!(
1206 error.to_string().contains(
1207 "cannot merge 'count' in explicit fields and remainder: not both objects"
1208 )
1209 );
1210
1211 let Value::Object(mut remainder) = json!({"count": 1}) else {
1212 unreachable!();
1213 };
1214 let error = merge_explicit_value(
1215 &mut remainder,
1216 "count".to_string(),
1217 json!(1),
1218 &mut Vec::new(),
1219 )
1220 .unwrap_err();
1221 assert!(error.to_string().contains("cannot merge 'count'"));
1222
1223 let Value::Object(mut remainder) = json!({"nested": {"count": 1}}) else {
1224 unreachable!();
1225 };
1226 let error = merge_explicit_value(
1227 &mut remainder,
1228 "nested".to_string(),
1229 json!({"count": 2}),
1230 &mut Vec::new(),
1231 )
1232 .unwrap_err();
1233 assert!(error.to_string().contains("cannot merge 'nested.count'"));
1234 Ok(())
1235 }
1236}