diff --git a/common/functions/src/scalars/function_adapter.rs b/common/functions/src/scalars/function_adapter.rs index 673b4f9fef9f2..373a026915d17 100644 --- a/common/functions/src/scalars/function_adapter.rs +++ b/common/functions/src/scalars/function_adapter.rs @@ -142,7 +142,7 @@ impl Function for FunctionAdapter { .collect::>(); let col = self.eval(&columns, 1)?; - let col = if col.is_const() && col.len() == 1 { + let col = if col.is_const() && col.len() != input_rows { col.replicate(&[input_rows]) } else if col.is_null() { NullColumn::new(input_rows).arc() @@ -171,7 +171,7 @@ impl Function for FunctionAdapter { if is_all_null { // If only null, return null directly. let args = columns.iter().map(|v| v.data_type()).collect::>(); - let inner_type = inner.return_type(args.as_slice())?; + let inner_type = remove_nullable(&inner.return_type(args.as_slice())?); return Ok(Arc::new(NullableColumn::new( inner_type .create_constant_column(&inner_type.default_value(), input_rows)?, @@ -206,12 +206,24 @@ impl Function for FunctionAdapter { }); let col = if col.is_nullable() { - let nullable_column: &NullableColumn = Series::check_get(&col)?; - NullableColumn::new(nullable_column.inner().clone(), validity) + // Constant(Nullable(column))? + if col.is_const() { + let c: &ConstColumn = unsafe { Series::static_cast(&col) }; + let nullable_column: &NullableColumn = + unsafe { Series::static_cast(c.inner()) }; + ConstColumn::new( + NullableColumn::new(nullable_column.inner().clone(), validity).arc(), + input_rows, + ) + .arc() + } else { + let nullable_column: &NullableColumn = Series::check_get(&col)?; + NullableColumn::new(nullable_column.inner().clone(), validity).arc() + } } else { - NullableColumn::new(col, validity) + NullableColumn::new(col, validity).arc() }; - return Ok(Arc::new(col)); + return Ok(col); } } diff --git a/common/functions/src/scalars/others/inet_aton.rs b/common/functions/src/scalars/others/inet_aton.rs index 4072b7b858e31..d5c2210bc1305 100644 --- a/common/functions/src/scalars/others/inet_aton.rs +++ b/common/functions/src/scalars/others/inet_aton.rs @@ -34,7 +34,6 @@ pub type InetAtonFunction = InetAtonFunctionImpl; #[derive(Clone)] pub struct InetAtonFunctionImpl { display_name: String, - result_type: DataTypePtr, } impl InetAtonFunctionImpl { @@ -42,36 +41,16 @@ impl InetAtonFunctionImpl Result> { - let result_type = if SUPPRESS_PARSE_ERROR { - let input_type = remove_nullable(args[0]); - match input_type.data_type_id() { - TypeID::Null => NullType::arc(), - // For invalid input, we suppress parse error and return null. So the return type must be nullable. - TypeID::String => NullableType::arc(UInt32Type::arc()), - _ => { - return Err(ErrorCode::IllegalDataType(format!( - "Expected string or null type, but got {}", - args[0].name() - ))) - } - } - } else { - assert_string(args[0])?; - UInt32Type::arc() - }; + assert_string(args[0])?; Ok(Box::new(InetAtonFunctionImpl:: { display_name: display_name.to_string(), - result_type, })) } pub fn desc() -> TypedFunctionDescription { - let mut features = FunctionFeatures::default().deterministic().num_arguments(1); - if SUPPRESS_PARSE_ERROR { - features = features.disable_passthrough_null() - } - TypedFunctionDescription::creator(Box::new(Self::try_create)).features(features) + TypedFunctionDescription::creator(Box::new(Self::try_create)) + .features(FunctionFeatures::default().deterministic().num_arguments(1)) } } @@ -81,14 +60,14 @@ impl Function for InetAtonFunctionImpl Result { - Ok(self.result_type.clone()) + if SUPPRESS_PARSE_ERROR { + Ok(NullableType::arc(UInt32Type::arc())) + } else { + Ok(UInt32Type::arc()) + } } fn eval(&self, columns: &ColumnsWithField, input_rows: usize) -> Result { - if columns[0].column().data_type_id() == TypeID::Null { - return NullType::arc().create_constant_column(&DataValue::Null, input_rows); - } - let viewer = Vu8::try_create_viewer(columns[0].column())?; let viewer_iter = viewer.iter(); diff --git a/common/functions/src/scalars/others/inet_ntoa.rs b/common/functions/src/scalars/others/inet_ntoa.rs index 6c3b16fa4df13..65645efeac3d4 100644 --- a/common/functions/src/scalars/others/inet_ntoa.rs +++ b/common/functions/src/scalars/others/inet_ntoa.rs @@ -38,37 +38,20 @@ pub type InetNtoaFunction = InetNtoaFunctionImpl; #[derive(Clone)] pub struct InetNtoaFunctionImpl { display_name: String, - result_type: DataTypePtr, } impl InetNtoaFunctionImpl { pub fn try_create(display_name: &str, args: &[&DataTypePtr]) -> Result> { - let result_type = if SUPPRESS_CAST_ERROR { - if args[0].data_type_id() == TypeID::Null { - NullType::arc() - } else { - let input_type = remove_nullable(args[0]); - assert_numeric(&input_type)?; - // For invalid input, the function should return null. So the return type must be nullable. - NullableType::arc(StringType::arc()) - } - } else { - assert_numeric(args[0])?; - StringType::arc() - }; + assert_numeric(args[0])?; Ok(Box::new(InetNtoaFunctionImpl:: { display_name: display_name.to_string(), - result_type, })) } pub fn desc() -> TypedFunctionDescription { - let mut features = FunctionFeatures::default().deterministic().num_arguments(1); - if SUPPRESS_CAST_ERROR { - features = features.disable_passthrough_null() - } - TypedFunctionDescription::creator(Box::new(Self::try_create)).features(features) + TypedFunctionDescription::creator(Box::new(Self::try_create)) + .features(FunctionFeatures::default().deterministic().num_arguments(1)) } } @@ -78,14 +61,14 @@ impl Function for InetNtoaFunctionImpl Result { - Ok(self.result_type.clone()) + if SUPPRESS_CAST_ERROR { + Ok(NullableType::arc(StringType::arc())) + } else { + Ok(StringType::arc()) + } } fn eval(&self, columns: &ColumnsWithField, input_rows: usize) -> Result { - if columns[0].column().data_type_id() == TypeID::Null { - return NullType::arc().create_constant_column(&DataValue::Null, input_rows); - } - if SUPPRESS_CAST_ERROR { let cast_to: DataTypePtr = Arc::new(NullableType::create(UInt32Type::arc())); let cast_options = CastOptions { diff --git a/common/functions/src/scalars/semi_structureds/check_json.rs b/common/functions/src/scalars/semi_structureds/check_json.rs index 128e4897885e3..b57a5fff37206 100644 --- a/common/functions/src/scalars/semi_structureds/check_json.rs +++ b/common/functions/src/scalars/semi_structureds/check_json.rs @@ -15,15 +15,14 @@ use std::fmt; use std::sync::Arc; -use common_arrow::arrow::bitmap::Bitmap; use common_datavalues::prelude::*; use common_exception::ErrorCode; use common_exception::Result; use serde_json::Value as JsonValue; use crate::scalars::Function; -use crate::scalars::FunctionDescription; use crate::scalars::FunctionFeatures; +use crate::scalars::TypedFunctionDescription; #[derive(Clone)] pub struct CheckJsonFunction { @@ -31,19 +30,15 @@ pub struct CheckJsonFunction { } impl CheckJsonFunction { - pub fn try_create(display_name: &str) -> Result> { + pub fn try_create(display_name: &str, _args: &[&DataTypePtr]) -> Result> { Ok(Box::new(CheckJsonFunction { display_name: display_name.to_string(), })) } - pub fn desc() -> FunctionDescription { - FunctionDescription::creator(Box::new(Self::try_create)).features( - FunctionFeatures::default() - .deterministic() - .monotonicity() - .num_arguments(1), - ) + pub fn desc() -> TypedFunctionDescription { + TypedFunctionDescription::creator(Box::new(Self::try_create)) + .features(FunctionFeatures::default().deterministic().num_arguments(1)) } } @@ -52,28 +47,13 @@ impl Function for CheckJsonFunction { &*self.display_name } - fn return_type(&self, args: &[&DataTypePtr]) -> Result { - if args[0].data_type_id() == TypeID::Null { - return Ok(NullType::arc()); - } - + fn return_type(&self, _args: &[&DataTypePtr]) -> Result { Ok(Arc::new(NullableType::create(StringType::arc()))) } fn eval(&self, columns: &ColumnsWithField, input_rows: usize) -> Result { - let data_type = remove_nullable(columns[0].field().data_type()); - let mut column = columns[0].column(); - let mut _all_null = false; - let mut source_valids: Option<&Bitmap> = None; - if column.is_nullable() { - (_all_null, source_valids) = column.validity(); - let nullable_column: &NullableColumn = Series::check_get(column)?; - column = nullable_column.inner(); - } - - if data_type.data_type_id() == TypeID::Null { - return NullType::arc().create_constant_column(&DataValue::Null, input_rows); - } + let data_type = columns[0].field().data_type(); + let column = columns[0].column(); let mut builder = NullableColumnBuilder::::with_capacity(input_rows); @@ -83,14 +63,7 @@ impl Function for CheckJsonFunction { } } else if data_type.data_type_id() == TypeID::String { let c: &StringColumn = Series::check_get(column)?; - for (i, v) in c.iter().enumerate() { - if let Some(source_valids) = source_valids { - if !source_valids.get_bit(i) { - builder.append_null(); - continue; - } - } - + for v in c.iter() { match std::str::from_utf8(v) { Ok(v) => match serde_json::from_str::(v) { Ok(_v) => builder.append_null(), diff --git a/common/functions/src/scalars/semi_structureds/get.rs b/common/functions/src/scalars/semi_structureds/get.rs index 54b8f163eb5c4..08dcf4c86690f 100644 --- a/common/functions/src/scalars/semi_structureds/get.rs +++ b/common/functions/src/scalars/semi_structureds/get.rs @@ -13,7 +13,6 @@ // limitations under the License. use std::fmt; -use std::sync::Arc; use common_datavalues::prelude::*; use common_exception::ErrorCode; @@ -25,8 +24,8 @@ use sqlparser::parser::Parser; use sqlparser::tokenizer::Tokenizer; use crate::scalars::Function; -use crate::scalars::FunctionDescription; use crate::scalars::FunctionFeatures; +use crate::scalars::TypedFunctionDescription; pub type GetFunction = GetFunctionImpl; @@ -40,26 +39,7 @@ pub struct GetFunctionImpl { } impl GetFunctionImpl { - pub fn try_create(display_name: &str) -> Result> { - Ok(Box::new(GetFunctionImpl:: { - display_name: display_name.to_string(), - })) - } - - pub fn desc() -> FunctionDescription { - FunctionDescription::creator(Box::new(Self::try_create)) - .features(FunctionFeatures::default().deterministic().num_arguments(2)) - } -} - -impl Function - for GetFunctionImpl -{ - fn name(&self) -> &str { - &*self.display_name - } - - fn return_type(&self, args: &[&DataTypePtr]) -> Result { + pub fn try_create(display_name: &str, args: &[&DataTypePtr]) -> Result> { let data_type = args[0]; let path_type = args[1]; @@ -75,13 +55,32 @@ impl Function { return Err(ErrorCode::IllegalDataType(format!( "Invalid argument types for function '{}': ({:?}, {:?})", - self.display_name.to_uppercase(), + display_name.to_uppercase(), data_type, path_type ))); } - Ok(Arc::new(NullableType::create(VariantType::arc()))) + Ok(Box::new(GetFunctionImpl:: { + display_name: display_name.to_string(), + })) + } + + pub fn desc() -> TypedFunctionDescription { + TypedFunctionDescription::creator(Box::new(Self::try_create)) + .features(FunctionFeatures::default().deterministic().num_arguments(2)) + } +} + +impl Function + for GetFunctionImpl +{ + fn name(&self) -> &str { + &*self.display_name + } + + fn return_type(&self, _args: &[&DataTypePtr]) -> Result { + Ok(NullableType::arc(VariantType::arc())) } fn eval(&self, columns: &ColumnsWithField, input_rows: usize) -> Result { diff --git a/common/functions/src/scalars/semi_structureds/parse_json.rs b/common/functions/src/scalars/semi_structureds/parse_json.rs index 7e75926deff7a..e69e4ab43e46d 100644 --- a/common/functions/src/scalars/semi_structureds/parse_json.rs +++ b/common/functions/src/scalars/semi_structureds/parse_json.rs @@ -13,7 +13,6 @@ // limitations under the License. use std::fmt; -use std::sync::Arc; use common_datavalues::prelude::*; use common_exception::ErrorCode; @@ -21,8 +20,8 @@ use common_exception::Result; use serde_json::Value as JsonValue; use crate::scalars::Function; -use crate::scalars::FunctionDescription; use crate::scalars::FunctionFeatures; +use crate::scalars::TypedFunctionDescription; pub type TryParseJsonFunction = ParseJsonFunctionImpl; @@ -31,23 +30,44 @@ pub type ParseJsonFunction = ParseJsonFunctionImpl; #[derive(Clone)] pub struct ParseJsonFunctionImpl { display_name: String, + result_type: DataTypePtr, } impl ParseJsonFunctionImpl { - pub fn try_create(display_name: &str) -> Result> { + pub fn try_create(display_name: &str, args: &[&DataTypePtr]) -> Result> { + let data_type = remove_nullable(args[0]); + if data_type.data_type_id() == TypeID::VariantArray + || data_type.data_type_id() == TypeID::VariantObject + { + return Err(ErrorCode::BadDataValueType(format!( + "Invalid argument types for function '{}': ({})", + display_name, + data_type.name() + ))); + } + + let result_type = if args[0].data_type_id() == TypeID::Null { + NullType::arc() + } else if args[0].is_nullable() || SUPPRESS_PARSE_ERROR { + NullableType::arc(VariantType::arc()) + } else { + VariantType::arc() + }; + Ok(Box::new(ParseJsonFunctionImpl:: { display_name: display_name.to_string(), + result_type, })) } - pub fn desc() -> FunctionDescription { + pub fn desc() -> TypedFunctionDescription { let mut features = FunctionFeatures::default().deterministic().num_arguments(1); // Null will cause parse error when SUPPRESS_PARSE_ERROR is false. // In this case we need to check null and skip the parsing, so passthrough_null should be false. if !SUPPRESS_PARSE_ERROR { features = features.disable_passthrough_null() } - FunctionDescription::creator(Box::new(Self::try_create)).features(features) + TypedFunctionDescription::creator(Box::new(Self::try_create)).features(features) } } @@ -56,33 +76,13 @@ impl Function for ParseJsonFunctionImpl Result { - if args[0].data_type_id() == TypeID::Null { - return Ok(NullType::arc()); - } - - if SUPPRESS_PARSE_ERROR { - // For invalid input, we suppress parse error and return null. So the return type must be nullable. - return Ok(Arc::new(NullableType::create(VariantType::arc()))); - } - - if args[0].is_nullable() { - return Ok(Arc::new(NullableType::create(VariantType::arc()))); - } - Ok(VariantType::arc()) + fn return_type(&self, _args: &[&DataTypePtr]) -> Result { + Ok(self.result_type.clone()) } fn eval(&self, columns: &ColumnsWithField, input_rows: usize) -> Result { let data_type = columns[0].field().data_type(); - if data_type.data_type_id() == TypeID::VariantArray - || data_type.data_type_id() == TypeID::VariantObject - { - return Err(ErrorCode::BadDataValueType(format!( - "Invalid argument types for function '{}': ({})", - self.display_name, - data_type.name() - ))); - } else if data_type.data_type_id() == TypeID::Null { + if data_type.data_type_id() == TypeID::Null { return NullType::arc().create_constant_column(&DataValue::Null, input_rows); } @@ -117,20 +117,13 @@ impl Function for ParseJsonFunctionImpl::with_capacity(input_rows); if data_type.data_type_id().is_numeric() @@ -139,7 +132,7 @@ impl Function for ParseJsonFunctionImpl { for (i, v) in values.iter().enumerate() { if let Some(valids) = valids { diff --git a/common/functions/src/scalars/semi_structureds/semi_structured.rs b/common/functions/src/scalars/semi_structureds/semi_structured.rs index 7bef21b09734f..c0de475f71eb3 100644 --- a/common/functions/src/scalars/semi_structureds/semi_structured.rs +++ b/common/functions/src/scalars/semi_structureds/semi_structured.rs @@ -24,11 +24,11 @@ pub struct SemiStructuredFunction; impl SemiStructuredFunction { pub fn register(factory: &mut FunctionFactory) { - factory.register("parse_json", ParseJsonFunction::desc()); - factory.register("try_parse_json", TryParseJsonFunction::desc()); - factory.register("check_json", CheckJsonFunction::desc()); - factory.register("get", GetFunction::desc()); - factory.register("get_ignore_case", GetIgnoreCaseFunction::desc()); - factory.register("get_path", GetPathFunction::desc()); + factory.register_typed("parse_json", ParseJsonFunction::desc()); + factory.register_typed("try_parse_json", TryParseJsonFunction::desc()); + factory.register_typed("check_json", CheckJsonFunction::desc()); + factory.register_typed("get", GetFunction::desc()); + factory.register_typed("get_ignore_case", GetIgnoreCaseFunction::desc()); + factory.register_typed("get_path", GetPathFunction::desc()); } } diff --git a/common/functions/tests/it/scalars/others.rs b/common/functions/tests/it/scalars/others.rs index 977e9e294a12f..0b3fa3786fb3b 100644 --- a/common/functions/tests/it/scalars/others.rs +++ b/common/functions/tests/it/scalars/others.rs @@ -300,7 +300,7 @@ fn test_try_inet_aton_function() -> Result<()> { ]; let test_func = TryInetAtonFunction::try_create("try_inet_aton", &[&StringType::arc()])?; - test_scalar_functions(test_func, &tests, false) + test_scalar_functions(test_func, &tests, true) } #[test] @@ -389,7 +389,7 @@ fn test_try_inet_ntoa_function() -> Result<()> { for (typ, test) in tests { match TryInetNtoaFunction::try_create("try_inet_ntoa", &[&typ]) { Ok(f) => { - test_scalar_functions(f, &[test], false)?; + test_scalar_functions(f, &[test], true)?; } Err(cause) => { assert_eq!(test.error, cause.message(), "{}", test.name); diff --git a/common/functions/tests/it/scalars/semi_structureds/check_json.rs b/common/functions/tests/it/scalars/semi_structureds/check_json.rs index fee0590208fa6..0aacc805489f8 100644 --- a/common/functions/tests/it/scalars/semi_structureds/check_json.rs +++ b/common/functions/tests/it/scalars/semi_structureds/check_json.rs @@ -25,6 +25,29 @@ use crate::scalars::scalar_function2_test::ScalarFunctionTest; fn test_check_json_function() -> Result<()> { use common_datavalues::prelude::*; + let types = vec![ + BooleanType::arc(), + Int16Type::arc(), + Float64Type::arc(), + StringType::arc(), + StringType::arc(), + StringType::arc(), + StringType::arc(), + NullableType::arc(BooleanType::arc()), + NullableType::arc(Int16Type::arc()), + NullableType::arc(Float64Type::arc()), + NullableType::arc(StringType::arc()), + NullableType::arc(StringType::arc()), + NullableType::arc(StringType::arc()), + NullableType::arc(StringType::arc()), + Arc::new(ArrayType::create(StringType::arc())), + Arc::new(StructType::create( + vec!["date".to_owned(), "integer".to_owned()], + vec![Date32Type::arc(), Int8Type::arc()], + )), + VariantType::arc(), + NullType::arc(), + ]; let tests = vec![ ScalarFunctionTest { name: "check_json_bool", @@ -203,5 +226,13 @@ fn test_check_json_function() -> Result<()> { }, ]; - test_scalar_functions(CheckJsonFunction::try_create("check_json")?, &tests, false) + for (typ, test) in types.iter().zip(tests) { + test_scalar_functions( + CheckJsonFunction::try_create("check_json", &[typ])?, + &[test], + true, + )?; + } + + Ok(()) } diff --git a/common/functions/tests/it/scalars/semi_structureds/get.rs b/common/functions/tests/it/scalars/semi_structureds/get.rs index af571370a335b..0780d8e65101a 100644 --- a/common/functions/tests/it/scalars/semi_structureds/get.rs +++ b/common/functions/tests/it/scalars/semi_structureds/get.rs @@ -25,6 +25,12 @@ use crate::scalars::scalar_function2_test::ScalarFunctionTest; fn test_get_function() -> Result<()> { use common_datavalues::prelude::*; + let types = vec![ + [VariantType::arc(), StringType::arc()], + [VariantType::arc(), UInt32Type::arc()], + [StringType::arc(), Int32Type::arc()], + ]; + let tests = vec![ ScalarFunctionTest { name: "get_by_field_name", @@ -70,13 +76,28 @@ fn test_get_function() -> Result<()> { }, ]; - test_scalar_functions(GetFunction::try_create("get")?, &tests, false) + for (typ, test) in types.iter().zip(tests) { + match GetFunction::try_create("get", &typ.iter().collect::>()) { + Ok(f) => { + test_scalar_functions(f, &[test], true)?; + } + Err(cause) => { + assert_eq!(test.error, cause.message(), "{}", test.name); + } + } + } + + Ok(()) } #[test] fn test_get_ignore_case_function() -> Result<()> { use common_datavalues::prelude::*; + let types = vec![[VariantType::arc(), StringType::arc()], [ + StringType::arc(), + Int32Type::arc(), + ]]; let tests = vec![ ScalarFunctionTest { name: "get_by_field_name", @@ -101,17 +122,29 @@ fn test_get_ignore_case_function() -> Result<()> { }, ]; - test_scalar_functions( - GetIgnoreCaseFunction::try_create("get_ignore_case")?, - &tests, - false, - ) + for (typ, test) in types.iter().zip(tests) { + match GetIgnoreCaseFunction::try_create("get_ignore_case", &typ.iter().collect::>()) + { + Ok(f) => { + test_scalar_functions(f, &[test], true)?; + } + Err(cause) => { + assert_eq!(test.error, cause.message(), "{}", test.name); + } + } + } + + Ok(()) } #[test] fn test_get_path_function() -> Result<()> { use common_datavalues::prelude::*; + let types = vec![[VariantType::arc(), StringType::arc()], [ + StringType::arc(), + Int32Type::arc(), + ]]; let tests = vec![ ScalarFunctionTest { name: "get_by_path", @@ -139,5 +172,16 @@ fn test_get_path_function() -> Result<()> { }, ]; - test_scalar_functions(GetPathFunction::try_create("get_path")?, &tests, false) + for (typ, test) in types.iter().zip(tests) { + match GetPathFunction::try_create("get_path", &typ.iter().collect::>()) { + Ok(f) => { + test_scalar_functions(f, &[test], true)?; + } + Err(cause) => { + assert_eq!(test.error, cause.message(), "{}", test.name); + } + } + } + + Ok(()) } diff --git a/common/functions/tests/it/scalars/semi_structureds/parse_json.rs b/common/functions/tests/it/scalars/semi_structureds/parse_json.rs index e744d7c673b77..da0c0c1dbf2f1 100644 --- a/common/functions/tests/it/scalars/semi_structureds/parse_json.rs +++ b/common/functions/tests/it/scalars/semi_structureds/parse_json.rs @@ -25,6 +25,22 @@ use crate::scalars::scalar_function2_test::ScalarFunctionTest; fn test_parse_json_function() -> Result<()> { use common_datavalues::prelude::*; + let types = vec![ + BooleanType::arc(), + Int16Type::arc(), + Float64Type::arc(), + StringType::arc(), + StringType::arc(), + StringType::arc(), + StringType::arc(), + NullableType::arc(BooleanType::arc()), + NullableType::arc(Int16Type::arc()), + NullableType::arc(Float64Type::arc()), + NullableType::arc(StringType::arc()), + NullableType::arc(StringType::arc()), + NullableType::arc(StringType::arc()), + NullableType::arc(StringType::arc()), + ]; let tests = vec![ ScalarFunctionTest { name: "parse_json_bool", @@ -168,13 +184,31 @@ fn test_parse_json_function() -> Result<()> { }, ]; - test_scalar_functions(ParseJsonFunction::try_create("parse_json")?, &tests, false) + for (typ, test) in types.iter().zip(tests) { + test_scalar_functions( + ParseJsonFunction::try_create("parse_json", &[typ])?, + &[test], + false, + )?; + } + + Ok(()) } #[test] fn test_try_parse_json_function() -> Result<()> { use common_datavalues::prelude::*; + let types = vec![ + BooleanType::arc(), + Int16Type::arc(), + Float64Type::arc(), + StringType::arc(), + StringType::arc(), + StringType::arc(), + StringType::arc(), + ]; + let tests = vec![ ScalarFunctionTest { name: "parse_json_bool", @@ -248,9 +282,13 @@ fn test_try_parse_json_function() -> Result<()> { }, ]; - test_scalar_functions( - TryParseJsonFunction::try_create("try_parse_json")?, - &tests, - false, - ) + for (typ, test) in types.iter().zip(tests) { + test_scalar_functions( + TryParseJsonFunction::try_create("try_parse_json", &[typ])?, + &[test], + true, + )?; + } + + Ok(()) }