Skip to main content

common_function/scalars/json/
json_get.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::sync::Arc;
16
17use arrow::array::{ArrayRef, BinaryViewArray, new_null_array};
18use arrow::compute;
19use arrow_schema::Field;
20use datafusion_common::arrow::array::{
21    Array, AsArray, BinaryViewBuilder, BooleanBuilder, Float64Builder, Int64Builder,
22    StringViewBuilder,
23};
24use datafusion_common::arrow::datatypes::DataType;
25use datafusion_common::{DataFusionError, Result, ScalarValue, exec_datafusion_err, exec_err};
26use datafusion_expr::{ColumnarValue, ScalarFunctionArgs, Signature, Volatility};
27use datatypes::extension::json::is_json2_extension_type;
28use datatypes::vectors::json::array::JsonArray;
29use derive_more::Display;
30
31use crate::function::{Function, extract_args};
32use crate::helper;
33
34fn get_json_by_path(json: &[u8], path: &str) -> Option<Vec<u8>> {
35    let json_path = jsonb::jsonpath::parse_json_path(path.as_bytes());
36    match json_path {
37        Ok(json_path) => {
38            let mut sub_jsonb = Vec::new();
39            let mut sub_offsets = Vec::new();
40            match jsonb::get_by_path(json, json_path, &mut sub_jsonb, &mut sub_offsets) {
41                Ok(_) => Some(sub_jsonb),
42                Err(_) => None,
43            }
44        }
45        _ => None,
46    }
47}
48
49trait JsonGetResultBuilder {
50    fn append_value(&mut self, value: &[u8]) -> Result<()>;
51
52    fn append_null(&mut self);
53
54    fn build(&mut self) -> ArrayRef;
55}
56
57fn result_builder(len: usize, with_type: &DataType) -> Result<Box<dyn JsonGetResultBuilder>> {
58    let builder = match with_type {
59        DataType::Utf8 | DataType::LargeUtf8 | DataType::Utf8View => {
60            Box::new(StringResultBuilder(StringViewBuilder::with_capacity(len)))
61                as Box<dyn JsonGetResultBuilder>
62        }
63        DataType::Int64 => Box::new(IntResultBuilder(Int64Builder::with_capacity(len))),
64        DataType::Float64 => Box::new(FloatResultBuilder(Float64Builder::with_capacity(len))),
65        DataType::Boolean => Box::new(BoolResultBuilder(BooleanBuilder::with_capacity(len))),
66        t => {
67            return exec_err!("json_get with unknown type {t}");
68        }
69    };
70    Ok(builder)
71}
72
73// TODO: refactor this to StringLikeArrayBuilder from Arrow 57
74struct StringResultBuilder(StringViewBuilder);
75
76impl JsonGetResultBuilder for StringResultBuilder {
77    fn append_value(&mut self, value: &[u8]) -> Result<()> {
78        self.0.append_option(jsonb::to_str(value).ok());
79        Ok(())
80    }
81
82    fn append_null(&mut self) {
83        self.0.append_null();
84    }
85
86    fn build(&mut self) -> ArrayRef {
87        Arc::new(self.0.finish())
88    }
89}
90
91#[derive(Default, Display, Debug)]
92#[display("{}", Self::NAME.to_ascii_uppercase())]
93pub struct JsonGetString(JsonGetWithType);
94
95impl JsonGetString {
96    pub const NAME: &'static str = "json_get_string";
97}
98
99impl Function for JsonGetString {
100    fn name(&self) -> &str {
101        Self::NAME
102    }
103
104    fn return_type(&self, _: &[DataType]) -> Result<DataType> {
105        Ok(DataType::Utf8View)
106    }
107
108    fn signature(&self) -> &Signature {
109        &self.0.signature
110    }
111
112    fn invoke_with_args(&self, mut args: ScalarFunctionArgs) -> Result<ColumnarValue> {
113        args.args
114            .push(ColumnarValue::Scalar(ScalarValue::Utf8View(None)));
115        self.0.invoke_with_args(args)
116    }
117}
118
119struct IntResultBuilder(Int64Builder);
120
121impl JsonGetResultBuilder for IntResultBuilder {
122    fn append_value(&mut self, value: &[u8]) -> Result<()> {
123        self.0.append_option(jsonb::to_i64(value).ok());
124        Ok(())
125    }
126
127    fn append_null(&mut self) {
128        self.0.append_null();
129    }
130
131    fn build(&mut self) -> ArrayRef {
132        Arc::new(self.0.finish())
133    }
134}
135
136#[derive(Default, Display, Debug)]
137#[display("{}", Self::NAME.to_ascii_uppercase())]
138pub struct JsonGetInt(JsonGetWithType);
139
140impl JsonGetInt {
141    pub const NAME: &'static str = "json_get_int";
142}
143
144impl Function for JsonGetInt {
145    fn name(&self) -> &str {
146        Self::NAME
147    }
148
149    fn return_type(&self, _: &[DataType]) -> Result<DataType> {
150        Ok(DataType::Int64)
151    }
152
153    fn signature(&self) -> &Signature {
154        &self.0.signature
155    }
156
157    fn invoke_with_args(&self, mut args: ScalarFunctionArgs) -> Result<ColumnarValue> {
158        args.args
159            .push(ColumnarValue::Scalar(ScalarValue::Int64(None)));
160        self.0.invoke_with_args(args)
161    }
162}
163
164struct FloatResultBuilder(Float64Builder);
165
166impl JsonGetResultBuilder for FloatResultBuilder {
167    fn append_value(&mut self, value: &[u8]) -> Result<()> {
168        self.0.append_option(jsonb::to_f64(value).ok());
169        Ok(())
170    }
171
172    fn append_null(&mut self) {
173        self.0.append_null();
174    }
175
176    fn build(&mut self) -> ArrayRef {
177        Arc::new(self.0.finish())
178    }
179}
180
181#[derive(Default, Display, Debug)]
182#[display("{}", Self::NAME.to_ascii_uppercase())]
183pub struct JsonGetFloat(JsonGetWithType);
184
185impl JsonGetFloat {
186    pub const NAME: &'static str = "json_get_float";
187}
188
189impl Function for JsonGetFloat {
190    fn name(&self) -> &str {
191        Self::NAME
192    }
193
194    fn return_type(&self, _: &[DataType]) -> Result<DataType> {
195        Ok(DataType::Float64)
196    }
197
198    fn signature(&self) -> &Signature {
199        &self.0.signature
200    }
201
202    fn invoke_with_args(&self, mut args: ScalarFunctionArgs) -> Result<ColumnarValue> {
203        args.args
204            .push(ColumnarValue::Scalar(ScalarValue::Float64(None)));
205        self.0.invoke_with_args(args)
206    }
207}
208
209struct BoolResultBuilder(BooleanBuilder);
210
211impl JsonGetResultBuilder for BoolResultBuilder {
212    fn append_value(&mut self, value: &[u8]) -> Result<()> {
213        self.0.append_option(jsonb::to_bool(value).ok());
214        Ok(())
215    }
216
217    fn append_null(&mut self) {
218        self.0.append_null();
219    }
220
221    fn build(&mut self) -> ArrayRef {
222        Arc::new(self.0.finish())
223    }
224}
225
226#[derive(Default, Display, Debug)]
227#[display("{}", Self::NAME.to_ascii_uppercase())]
228pub struct JsonGetBool(JsonGetWithType);
229
230impl JsonGetBool {
231    pub const NAME: &'static str = "json_get_bool";
232}
233
234impl Function for JsonGetBool {
235    fn name(&self) -> &str {
236        Self::NAME
237    }
238
239    fn return_type(&self, _: &[DataType]) -> Result<DataType> {
240        Ok(DataType::Boolean)
241    }
242
243    fn signature(&self) -> &Signature {
244        &self.0.signature
245    }
246
247    fn invoke_with_args(&self, mut args: ScalarFunctionArgs) -> Result<ColumnarValue> {
248        args.args
249            .push(ColumnarValue::Scalar(ScalarValue::Boolean(None)));
250        self.0.invoke_with_args(args)
251    }
252}
253
254fn jsonb_get(
255    jsons: &BinaryViewArray,
256    path: &str,
257    builder: &mut dyn JsonGetResultBuilder,
258) -> Result<()> {
259    let size = jsons.len();
260    for i in 0..size {
261        let json = jsons.is_valid(i).then(|| jsons.value(i));
262        let result = match json {
263            Some(json) => get_json_by_path(json, path),
264            _ => None,
265        };
266        if let Some(v) = result {
267            builder.append_value(&v)?;
268        } else {
269            builder.append_null();
270        }
271    }
272    Ok(())
273}
274
275fn json_struct_get(array: &ArrayRef, path: &str, with_type: &DataType) -> Result<ArrayRef> {
276    let segments = path
277        .trim_start_matches("$")
278        .split('.')
279        .filter(|segment| !segment.is_empty())
280        .collect::<Vec<_>>();
281
282    let mut curr = array.clone();
283
284    for (idx, segment) in segments.iter().enumerate() {
285        if curr.data_type().is_binary() {
286            let target = nested_projection_type(&segments[idx..], with_type);
287            curr = JsonArray::from(&curr)
288                .project_to(&target)
289                .map_err(|e| exec_datafusion_err!("{e}"))?;
290        }
291
292        let Some(json) = curr.as_struct_opt() else {
293            return exec_err!("unknown JSON array datatype: {}", curr.data_type());
294        };
295        let Some(sub_json) = json.column_by_name(segment) else {
296            return Ok(new_null_array(with_type, array.len()));
297        };
298        curr = sub_json.clone();
299    }
300
301    if curr.data_type() == with_type {
302        Ok(curr)
303    } else {
304        JsonArray::from(&curr)
305            .project_to(with_type)
306            .map_err(|e| exec_datafusion_err!("{e}"))
307    }
308}
309
310/// Builds a nested struct type for projecting the remaining JSON path.
311///
312/// For example, path `["a", "b"]` with an `Int64` leaf produces
313/// `Struct<a: Struct<b: Int64>>`.
314fn nested_projection_type(path: &[&str], leaf_type: &DataType) -> DataType {
315    path.iter()
316        .rev()
317        .fold(leaf_type.clone(), |data_type, name| {
318            DataType::Struct(vec![Arc::new(Field::new(*name, data_type, true))].into())
319        })
320}
321
322/// This function is mostly called as `json_get(value, 'attr')::type` and rewritten by
323/// `json_get_rewriter::JsonGetRewriter` to `json_get(value, 'attr', NULL::type)`. So we
324/// use the third argument's type to determine the return type.
325#[derive(Debug, Display)]
326#[display("{}", Self::NAME.to_ascii_uppercase())]
327pub struct JsonGetWithType {
328    signature: Signature,
329}
330
331impl JsonGetWithType {
332    pub const NAME: &'static str = "json_get";
333}
334
335impl Default for JsonGetWithType {
336    fn default() -> Self {
337        Self {
338            signature: Signature::variadic_any(Volatility::Immutable),
339        }
340    }
341}
342
343impl Function for JsonGetWithType {
344    fn name(&self) -> &str {
345        Self::NAME
346    }
347
348    fn return_type(&self, _input_types: &[DataType]) -> datafusion_common::Result<DataType> {
349        Err(DataFusionError::Internal(
350            "This method isn't meant to be called".to_string(),
351        ))
352    }
353
354    fn return_field_from_args(
355        &self,
356        args: datafusion_expr::ReturnFieldArgs<'_>,
357    ) -> datafusion_common::Result<Arc<Field>> {
358        match args.scalar_arguments.get(2) {
359            Some(Some(v)) => {
360                let mut data_type = v.data_type();
361                if matches!(data_type, DataType::Utf8 | DataType::LargeUtf8) {
362                    data_type = DataType::Utf8View;
363                }
364
365                Ok(Arc::new(Field::new(self.name(), data_type, true)))
366            }
367            _ => Ok(Arc::new(Field::new(self.name(), DataType::Utf8View, true))),
368        }
369    }
370
371    fn signature(&self) -> &Signature {
372        &self.signature
373    }
374
375    fn invoke_with_args(
376        &self,
377        args: ScalarFunctionArgs,
378    ) -> datafusion_common::Result<ColumnarValue> {
379        let args_len = args.args.len();
380        if args_len != 2 && args_len != 3 {
381            return exec_err!("json_get expects 2 or 3 arguments, got {args_len}");
382        }
383
384        let arg0 = args.args[0].to_array(args.number_rows)?;
385        let len = arg0.len();
386
387        let path = if let ColumnarValue::Scalar(path) = &args.args[1]
388            && let Some(Some(path)) = path.try_as_str()
389        {
390            path
391        } else {
392            return exec_err!(
393                r#"json_get expects a string literal "path" argument, got {}"#,
394                args.args[1]
395            );
396        };
397
398        let with_type = args
399            .args
400            .get(2)
401            .map(|x| x.data_type())
402            .unwrap_or(DataType::Utf8View);
403
404        let result = match arg0.data_type() {
405            DataType::Binary | DataType::LargeBinary | DataType::BinaryView => {
406                let arg0 = compute::cast(&arg0, &DataType::BinaryView)?;
407
408                if args.arg_fields.first().is_some_and(is_json2_extension_type) {
409                    // Query concretization projects nested JSON2 paths as Struct arrays. A binary
410                    // JSON2 argument is therefore an already-selected scalar or root value that
411                    // only needs conversion from its JSONB representation to the requested type.
412                    JsonArray::from(&arg0)
413                        .project_to(&with_type)
414                        .map_err(|e| exec_datafusion_err!("{e:?}"))?
415                } else {
416                    let jsons = arg0.as_binary_view();
417                    let mut builder = result_builder(len, &with_type)?;
418                    jsonb_get(jsons, path, builder.as_mut())?;
419                    builder.build()
420                }
421            }
422            DataType::Struct(_) => json_struct_get(&arg0, path, &with_type)?,
423            _ => {
424                return exec_err!("JSON_GET not supported argument type {}", arg0.data_type());
425            }
426        };
427
428        Ok(ColumnarValue::Array(result))
429    }
430}
431
432/// Get the object from JSON value by path.
433#[derive(Display, Debug)]
434#[display("{}", Self::NAME.to_ascii_uppercase())]
435pub(super) struct JsonGetObject {
436    signature: Signature,
437}
438
439impl JsonGetObject {
440    const NAME: &'static str = "json_get_object";
441}
442
443impl Default for JsonGetObject {
444    fn default() -> Self {
445        Self {
446            signature: helper::one_of_sigs2(
447                vec![
448                    DataType::Binary,
449                    DataType::LargeBinary,
450                    DataType::BinaryView,
451                ],
452                vec![DataType::UInt8, DataType::LargeUtf8, DataType::Utf8View],
453            ),
454        }
455    }
456}
457
458impl Function for JsonGetObject {
459    fn name(&self) -> &str {
460        Self::NAME
461    }
462
463    fn return_type(&self, _: &[DataType]) -> datafusion_common::Result<DataType> {
464        Ok(DataType::BinaryView)
465    }
466
467    fn signature(&self) -> &Signature {
468        &self.signature
469    }
470
471    fn invoke_with_args(
472        &self,
473        args: ScalarFunctionArgs,
474    ) -> datafusion_common::Result<ColumnarValue> {
475        let [arg0, arg1] = extract_args(self.name(), &args)?;
476        let arg0 = compute::cast(&arg0, &DataType::BinaryView)?;
477        let jsons = arg0.as_binary_view();
478        let arg1 = compute::cast(&arg1, &DataType::Utf8View)?;
479        let paths = arg1.as_string_view();
480
481        let len = jsons.len();
482        let mut builder = BinaryViewBuilder::with_capacity(len);
483
484        for i in 0..len {
485            let json = jsons.is_valid(i).then(|| jsons.value(i));
486            let path = paths.is_valid(i).then(|| paths.value(i));
487            let result = if let (Some(json), Some(path)) = (json, path) {
488                let result = jsonb::jsonpath::parse_json_path(path.as_bytes()).and_then(|path| {
489                    let mut data = Vec::new();
490                    let mut offset = Vec::new();
491                    jsonb::get_by_path(json, path, &mut data, &mut offset)
492                        .map(|()| jsonb::is_object(&data).then_some(data))
493                });
494                result.map_err(|e| DataFusionError::Execution(e.to_string()))?
495            } else {
496                None
497            };
498            builder.append_option(result);
499        }
500
501        Ok(ColumnarValue::Array(Arc::new(builder.finish())))
502    }
503}
504
505#[cfg(test)]
506mod tests {
507    use std::sync::Arc;
508
509    use arrow::array::{BooleanArray, Int64Array, StructArray};
510    use arrow_schema::{Field, Fields};
511    use datafusion_common::ScalarValue;
512    use datafusion_common::arrow::array::{BinaryArray, BinaryViewArray, StringArray};
513    use datafusion_common::arrow::datatypes::{Float64Type, Int64Type};
514    use datatypes::types::parse_string_to_jsonb;
515    use serde_json::json;
516
517    use super::*;
518
519    /// Create a JSON object like this (as a one element struct array for testing):
520    ///
521    /// ```JSON
522    /// {
523    ///     "kind": "foo",
524    ///     "payload": {
525    ///         "code": 404,
526    ///         "success": false,
527    ///         "result": {
528    ///             "error": "not found",
529    ///             "time_cost": 1.234
530    ///         }
531    ///     }
532    /// }
533    /// ```
534    fn test_json_struct() -> ArrayRef {
535        let payload_fields = Fields::from(vec![
536            Field::new("code", DataType::Int64, true),
537            Field::new("success", DataType::Boolean, true),
538            Field::new("result", DataType::Binary, true),
539        ]);
540        Arc::new(StructArray::new(
541            vec![
542                Field::new("kind", DataType::Utf8, true),
543                Field::new("payload", DataType::Struct(payload_fields.clone()), true),
544            ]
545            .into(),
546            vec![
547                Arc::new(StringArray::from_iter([Some("foo")])) as ArrayRef,
548                Arc::new(StructArray::new(
549                    payload_fields,
550                    vec![
551                        Arc::new(Int64Array::from_iter([Some(404)])) as ArrayRef,
552                        Arc::new(BooleanArray::from_iter([Some(false)])),
553                        Arc::new(BinaryArray::from_iter([Some(
554                            json!({
555                                "error": "not found",
556                                "time_cost": 1.234
557                            })
558                            .to_string()
559                            .as_bytes(),
560                        )])),
561                    ],
562                    None,
563                )),
564            ],
565            None,
566        ))
567    }
568
569    #[test]
570    fn test_json_get_int() {
571        let json_get_int = JsonGetInt::default();
572
573        assert_eq!("json_get_int", json_get_int.name());
574        assert_eq!(
575            DataType::Int64,
576            json_get_int
577                .return_type(&[DataType::Binary, DataType::Utf8])
578                .unwrap()
579        );
580
581        let json_strings = [
582            r#"{"a": {"b": 2}, "b": 2, "c": 3}"#,
583            r#"{"a": 4, "b": {"c": 6}, "c": 6}"#,
584            r#"{"a": 7, "b": 8, "c": {"a": 7}}"#,
585        ];
586        let json_struct = test_json_struct();
587
588        let path_expects = vec![
589            ("$.a.b", Some(2)),
590            ("$.a", Some(4)),
591            ("$.c", None),
592            ("$.kind", None),
593            ("$.payload.code", Some(404)),
594            ("$.payload.success", Some(0)),
595            ("$.payload.result.time_cost", Some(1)),
596            ("$.payload.not-exists", None),
597            ("$.not-exists", None),
598            ("$", None),
599        ];
600
601        let mut jsons = json_strings
602            .iter()
603            .map(|s| {
604                let value = jsonb::parse_value(s.as_bytes()).unwrap();
605                Arc::new(BinaryArray::from_iter_values([value.to_vec()])) as ArrayRef
606            })
607            .collect::<Vec<_>>();
608        let json_struct_arrays =
609            std::iter::repeat_n(json_struct, path_expects.len() - jsons.len()).collect::<Vec<_>>();
610        jsons.extend(json_struct_arrays);
611
612        for i in 0..jsons.len() {
613            let json = &jsons[i];
614            let (path, expect) = path_expects[i];
615
616            let args = ScalarFunctionArgs {
617                args: vec![
618                    ColumnarValue::Array(json.clone()),
619                    ColumnarValue::Scalar(path.into()),
620                ],
621                arg_fields: vec![],
622                number_rows: 1,
623                return_field: Arc::new(Field::new("x", DataType::Int64, false)),
624                config_options: Arc::new(Default::default()),
625            };
626            let result = json_get_int
627                .invoke_with_args(args)
628                .and_then(|x| x.to_array(1))
629                .unwrap();
630
631            let result = result.as_primitive::<Int64Type>();
632            assert_eq!(1, result.len());
633            let actual = result.is_valid(0).then(|| result.value(0));
634            assert_eq!(actual, expect);
635        }
636    }
637
638    #[test]
639    fn test_json_get_float() {
640        let json_get_float = JsonGetFloat::default();
641
642        assert_eq!("json_get_float", json_get_float.name());
643        assert_eq!(
644            DataType::Float64,
645            json_get_float
646                .return_type(&[DataType::Binary, DataType::Utf8])
647                .unwrap()
648        );
649
650        let json_strings = [
651            r#"{"a": {"b": 2.1}, "b": 2.2, "c": 3.3}"#,
652            r#"{"a": 4.4, "b": {"c": 6.6}, "c": 6.6}"#,
653            r#"{"a": 7.7, "b": 8.8, "c": {"a": 7.7}}"#,
654        ];
655        let json_struct = test_json_struct();
656
657        let path_expects = vec![
658            ("$.a.b", Some(2.1)),
659            ("$.a", Some(4.4)),
660            ("$.c", None),
661            ("$.kind", None),
662            ("$.payload.code", Some(404.0)),
663            ("$.payload.success", Some(0.0)),
664            ("$.payload.result.time_cost", Some(1.234)),
665            ("$.payload.not-exists", None),
666            ("$.not-exists", None),
667            ("$", None),
668        ];
669
670        let mut jsons = json_strings
671            .iter()
672            .map(|s| {
673                let value = jsonb::parse_value(s.as_bytes()).unwrap();
674                Arc::new(BinaryArray::from_iter_values([value.to_vec()])) as ArrayRef
675            })
676            .collect::<Vec<_>>();
677        let json_struct_arrays =
678            std::iter::repeat_n(json_struct, path_expects.len() - jsons.len()).collect::<Vec<_>>();
679        jsons.extend(json_struct_arrays);
680
681        for i in 0..jsons.len() {
682            let json = &jsons[i];
683            let (path, expect) = path_expects[i];
684
685            let args = ScalarFunctionArgs {
686                args: vec![
687                    ColumnarValue::Array(json.clone()),
688                    ColumnarValue::Scalar(path.into()),
689                ],
690                arg_fields: vec![],
691                number_rows: 1,
692                return_field: Arc::new(Field::new("x", DataType::Float64, false)),
693                config_options: Arc::new(Default::default()),
694            };
695            let result = json_get_float
696                .invoke_with_args(args)
697                .and_then(|x| x.to_array(1))
698                .unwrap();
699
700            let result = result.as_primitive::<Float64Type>();
701            assert_eq!(1, result.len());
702            let actual = result.is_valid(0).then(|| result.value(0));
703            assert_eq!(actual, expect);
704        }
705    }
706
707    #[test]
708    fn test_json_get_bool() {
709        let json_get_bool = JsonGetBool::default();
710
711        assert_eq!("json_get_bool", json_get_bool.name());
712        assert_eq!(
713            DataType::Boolean,
714            json_get_bool
715                .return_type(&[DataType::Binary, DataType::Utf8])
716                .unwrap()
717        );
718
719        let json_strings = [
720            r#"{"a": {"b": true}, "b": false, "c": true}"#,
721            r#"{"a": false, "b": {"c": true}, "c": false}"#,
722            r#"{"a": true, "b": false, "c": {"a": true}}"#,
723        ];
724        let json_struct = test_json_struct();
725
726        let path_expects = vec![
727            ("$.a.b", Some(true)),
728            ("$.a", Some(false)),
729            ("$.c", None),
730            ("$.kind", None),
731            ("$.payload.code", Some(true)),
732            ("$.payload.success", Some(false)),
733            ("$.payload.result.time_cost", Some(true)),
734            ("$.payload.not-exists", None),
735            ("$.not-exists", None),
736            ("$", None),
737        ];
738
739        let mut jsons = json_strings
740            .iter()
741            .map(|s| {
742                let value = jsonb::parse_value(s.as_bytes()).unwrap();
743                Arc::new(BinaryArray::from_iter_values([value.to_vec()])) as ArrayRef
744            })
745            .collect::<Vec<_>>();
746        let json_struct_arrays =
747            std::iter::repeat_n(json_struct, path_expects.len() - jsons.len()).collect::<Vec<_>>();
748        jsons.extend(json_struct_arrays);
749
750        for i in 0..jsons.len() {
751            let json = &jsons[i];
752            let (path, expect) = path_expects[i];
753
754            let args = ScalarFunctionArgs {
755                args: vec![
756                    ColumnarValue::Array(json.clone()),
757                    ColumnarValue::Scalar(path.into()),
758                ],
759                arg_fields: vec![],
760                number_rows: 1,
761                return_field: Arc::new(Field::new("x", DataType::Boolean, false)),
762                config_options: Arc::new(Default::default()),
763            };
764            let result = json_get_bool
765                .invoke_with_args(args)
766                .and_then(|x| x.to_array(1))
767                .unwrap();
768
769            let result = result.as_boolean();
770            assert_eq!(1, result.len());
771            let actual = result.is_valid(0).then(|| result.value(0));
772            assert_eq!(actual, expect);
773        }
774    }
775
776    #[test]
777    fn test_json_get_string() {
778        let json_get_string = JsonGetString::default();
779
780        assert_eq!("json_get_string", json_get_string.name());
781        assert_eq!(
782            DataType::Utf8View,
783            json_get_string
784                .return_type(&[DataType::Binary, DataType::Utf8])
785                .unwrap()
786        );
787
788        let json_strings = [
789            r#"{"a": {"b": "a"}, "b": "b", "c": "c"}"#,
790            r#"{"a": "d", "b": {"c": "e"}, "c": "f"}"#,
791            r#"{"a": "g", "b": "h", "c": {"a": "g"}}"#,
792        ];
793        let json_struct = test_json_struct();
794
795        let paths = vec![
796            "$.a.b",
797            "$.a",
798            "",
799            "$.kind",
800            "$.payload.code",
801            "$.payload.result.time_cost",
802            "$.payload",
803            "$.payload.success",
804            "$.payload.result",
805            "$.payload.result.error",
806            "$.payload.result.not-exists",
807            "$.payload.not-exists",
808            "$.not-exists",
809            "$",
810        ];
811        let expects = [
812            Some("a"),
813            Some("d"),
814            None,
815            Some("foo"),
816            Some("404"),
817            Some("1.234"),
818            Some(
819                r#"{"code":404,"result":{"error":"not found","time_cost":1.234},"success":false}"#,
820            ),
821            Some("false"),
822            Some(r#"{"error":"not found","time_cost":1.234}"#),
823            Some("not found"),
824            None,
825            None,
826            None,
827            Some(
828                r#"{"kind":"foo","payload":{"code":404,"result":{"error":"not found","time_cost":1.234},"success":false}}"#,
829            ),
830        ];
831
832        let mut jsons = json_strings
833            .iter()
834            .map(|s| {
835                let value = jsonb::parse_value(s.as_bytes()).unwrap();
836                Arc::new(BinaryArray::from_iter_values([value.to_vec()])) as ArrayRef
837            })
838            .collect::<Vec<_>>();
839        let json_struct_arrays =
840            std::iter::repeat_n(json_struct, expects.len() - jsons.len()).collect::<Vec<_>>();
841        jsons.extend(json_struct_arrays);
842
843        for i in 0..jsons.len() {
844            let json = &jsons[i];
845            let path = paths[i];
846            let expect = expects[i];
847
848            let args = ScalarFunctionArgs {
849                args: vec![
850                    ColumnarValue::Array(json.clone()),
851                    ColumnarValue::Scalar(path.into()),
852                ],
853                arg_fields: vec![],
854                number_rows: 1,
855                return_field: Arc::new(Field::new("x", DataType::Utf8View, false)),
856                config_options: Arc::new(Default::default()),
857            };
858            let result = json_get_string
859                .invoke_with_args(args)
860                .and_then(|x| x.to_array(1))
861                .unwrap();
862
863            let result = result.as_string_view();
864            assert_eq!(1, result.len());
865            let actual = result.is_valid(0).then(|| result.value(0));
866            assert_eq!(actual, expect);
867        }
868    }
869
870    #[test]
871    fn test_json_get_object() -> Result<()> {
872        let udf = JsonGetObject::default();
873        assert_eq!("json_get_object", udf.name());
874        assert_eq!(
875            DataType::BinaryView,
876            udf.return_type(&[DataType::BinaryView, DataType::Utf8View])?
877        );
878
879        let json_value = parse_string_to_jsonb(r#"{"a": {"b": {"c": {"d": 1}}}}"#).unwrap();
880        let paths = vec!["$", "$.a", "$.a.b", "$.a.b.c", "$.a.b.c.d", "$.e", "$.a.e"];
881        let number_rows = paths.len();
882
883        let args = ScalarFunctionArgs {
884            args: vec![
885                ColumnarValue::Scalar(ScalarValue::Binary(Some(json_value))),
886                ColumnarValue::Array(Arc::new(StringArray::from_iter_values(paths))),
887            ],
888            arg_fields: vec![],
889            number_rows,
890            return_field: Arc::new(Field::new("x", DataType::Binary, false)),
891            config_options: Arc::new(Default::default()),
892        };
893        let result = udf
894            .invoke_with_args(args)
895            .and_then(|x| x.to_array(number_rows))?;
896        let result = result.as_binary_view();
897
898        let expected = &BinaryViewArray::from_iter(
899            vec![
900                Some(r#"{"a": {"b": {"c": {"d": 1}}}}"#),
901                Some(r#"{"b": {"c": {"d": 1}}}"#),
902                Some(r#"{"c": {"d": 1}}"#),
903                Some(r#"{"d": 1}"#),
904                None,
905                None,
906                None,
907            ]
908            .into_iter()
909            .map(|x| x.and_then(|s| parse_string_to_jsonb(s).ok())),
910        );
911        assert_eq!(result, expected);
912        Ok(())
913    }
914
915    #[test]
916    fn test_json_get_with_type() {
917        let json_get_with_type = JsonGetWithType::default();
918
919        assert_eq!("json_get", json_get_with_type.name());
920
921        let json_strings = [
922            r#"{"a": {"b": "a"}, "b": "b", "c": "c"}"#,
923            r#"{"a": "d", "b": {"c": "e"}, "c": "f"}"#,
924            r#"{"a": "g", "b": "h", "c": {"a": "g"}}"#,
925        ];
926        let json_struct = test_json_struct();
927
928        let paths = vec![
929            "$.a.b",
930            "$.a",
931            "",
932            "$.kind",
933            "$.payload.code",
934            "$.payload.result.time_cost",
935            "$.payload",
936            "$.payload.success",
937            "$.payload.result",
938            "$.payload.result.error",
939            "$.payload.result.not-exists",
940            "$.payload.not-exists",
941            "$.not-exists",
942            "$",
943        ];
944        let expects = [
945            Some("a"),
946            Some("d"),
947            None,
948            Some("foo"),
949            Some("404"),
950            Some("1.234"),
951            Some(
952                r#"{"code":404,"result":{"error":"not found","time_cost":1.234},"success":false}"#,
953            ),
954            Some("false"),
955            Some(r#"{"error":"not found","time_cost":1.234}"#),
956            Some("not found"),
957            None,
958            None,
959            None,
960            Some(
961                r#"{"kind":"foo","payload":{"code":404,"result":{"error":"not found","time_cost":1.234},"success":false}}"#,
962            ),
963        ];
964
965        let mut jsons = json_strings
966            .iter()
967            .map(|s| {
968                let value = jsonb::parse_value(s.as_bytes()).unwrap();
969                Arc::new(BinaryArray::from_iter_values([value.to_vec()])) as ArrayRef
970            })
971            .collect::<Vec<_>>();
972        let json_struct_arrays =
973            std::iter::repeat_n(json_struct, expects.len() - jsons.len()).collect::<Vec<_>>();
974        jsons.extend(json_struct_arrays);
975
976        for i in 0..jsons.len() {
977            let json = &jsons[i];
978            let path = paths[i];
979            let expect = expects[i];
980
981            let args = ScalarFunctionArgs {
982                args: vec![
983                    ColumnarValue::Array(json.clone()),
984                    ColumnarValue::Scalar(path.into()),
985                    ColumnarValue::Scalar(ScalarValue::Utf8View(None)),
986                ],
987                arg_fields: vec![],
988                number_rows: 1,
989                return_field: Arc::new(Field::new("x", DataType::Utf8View, false)),
990                config_options: Arc::new(Default::default()),
991            };
992            let result = json_get_with_type
993                .invoke_with_args(args)
994                .and_then(|x| x.to_array(1))
995                .unwrap();
996
997            let result = result.as_string_view();
998            assert_eq!(1, result.len());
999            let actual = result.is_valid(0).then(|| result.value(0));
1000            assert_eq!(actual, expect);
1001        }
1002
1003        let json_strings = [
1004            r#"{"a": {"b": 2}, "b": 2, "c": 3}"#,
1005            r#"{"a": 4, "b": {"c": 6}, "c": 6}"#,
1006            r#"{"a": 7, "b": 8, "c": {"a": 7}}"#,
1007        ];
1008        let paths = ["$.a.b", "$.a", "$.c", "$.payload.code"];
1009        let expects = [Some(2), Some(4), None, Some(404)];
1010
1011        for (i, (path, expect)) in paths.iter().zip(expects.iter()).enumerate() {
1012            let json = if i < json_strings.len() {
1013                let value = jsonb::parse_value(json_strings[i].as_bytes()).unwrap();
1014                Arc::new(BinaryArray::from_iter_values([value.to_vec()])) as ArrayRef
1015            } else {
1016                test_json_struct()
1017            };
1018
1019            let args = ScalarFunctionArgs {
1020                args: vec![
1021                    ColumnarValue::Array(json),
1022                    ColumnarValue::Scalar((*path).into()),
1023                    ColumnarValue::Scalar(ScalarValue::Int64(None)),
1024                ],
1025                arg_fields: vec![],
1026                number_rows: 1,
1027                return_field: Arc::new(Field::new("x", DataType::Int64, false)),
1028                config_options: Arc::new(Default::default()),
1029            };
1030            let result = json_get_with_type
1031                .invoke_with_args(args)
1032                .and_then(|x| x.to_array(1))
1033                .unwrap();
1034
1035            let result = result.as_primitive::<Int64Type>();
1036            assert_eq!(1, result.len());
1037            let actual = result.is_valid(0).then(|| result.value(0));
1038            assert_eq!(actual, *expect);
1039        }
1040
1041        let json_strings = [
1042            r#"{"a": {"b": 2.1}, "b": 2.2, "c": 3.3}"#,
1043            r#"{"a": 4.4, "b": {"c": 6.6}, "c": 6.6}"#,
1044            r#"{"a": 7.7, "b": 8.8, "c": {"a": 7.7}}"#,
1045        ];
1046        let paths = ["$.a.b", "$.a", "$.c", "$.payload.result.time_cost"];
1047        let expects = [Some(2.1), Some(4.4), None, Some(1.234)];
1048
1049        for (i, (path, expect)) in paths.iter().zip(expects.iter()).enumerate() {
1050            let json = if i < json_strings.len() {
1051                let value = jsonb::parse_value(json_strings[i].as_bytes()).unwrap();
1052                Arc::new(BinaryArray::from_iter_values([value.to_vec()])) as ArrayRef
1053            } else {
1054                test_json_struct()
1055            };
1056
1057            let args = ScalarFunctionArgs {
1058                args: vec![
1059                    ColumnarValue::Array(json),
1060                    ColumnarValue::Scalar((*path).into()),
1061                    ColumnarValue::Scalar(ScalarValue::Float64(None)),
1062                ],
1063                arg_fields: vec![],
1064                number_rows: 1,
1065                return_field: Arc::new(Field::new("x", DataType::Float64, false)),
1066                config_options: Arc::new(Default::default()),
1067            };
1068            let result = json_get_with_type
1069                .invoke_with_args(args)
1070                .and_then(|x| x.to_array(1))
1071                .unwrap();
1072
1073            let result = result.as_primitive::<Float64Type>();
1074            assert_eq!(1, result.len());
1075            let actual = result.is_valid(0).then(|| result.value(0));
1076            assert_eq!(actual, *expect);
1077        }
1078
1079        let json_strings = [
1080            r#"{"a": {"b": true}, "b": false, "c": true}"#,
1081            r#"{"a": false, "b": {"c": true}, "c": false}"#,
1082            r#"{"a": true, "b": false, "c": {"a": true}}"#,
1083        ];
1084        let paths = ["$.a.b", "$.a", "$.c", "$.payload.success"];
1085        let expects = [Some(true), Some(false), None, Some(false)];
1086
1087        for (i, (path, expect)) in paths.iter().zip(expects.iter()).enumerate() {
1088            let json = if i < json_strings.len() {
1089                let value = jsonb::parse_value(json_strings[i].as_bytes()).unwrap();
1090                Arc::new(BinaryArray::from_iter_values([value.to_vec()])) as ArrayRef
1091            } else {
1092                test_json_struct()
1093            };
1094
1095            let args = ScalarFunctionArgs {
1096                args: vec![
1097                    ColumnarValue::Array(json),
1098                    ColumnarValue::Scalar((*path).into()),
1099                    ColumnarValue::Scalar(ScalarValue::Boolean(None)),
1100                ],
1101                arg_fields: vec![],
1102                number_rows: 1,
1103                return_field: Arc::new(Field::new("x", DataType::Boolean, false)),
1104                config_options: Arc::new(Default::default()),
1105            };
1106            let result = json_get_with_type
1107                .invoke_with_args(args)
1108                .and_then(|x| x.to_array(1))
1109                .unwrap();
1110
1111            let result = result.as_boolean();
1112            assert_eq!(1, result.len());
1113            let actual = result.is_valid(0).then(|| result.value(0));
1114            assert_eq!(actual, *expect);
1115        }
1116    }
1117}