From aef0499492abf29371bcc8f7166a0e6c19ddaf38 Mon Sep 17 00:00:00 2001 From: baishen Date: Mon, 17 Feb 2025 15:08:23 +0800 Subject: [PATCH] fix(query): fix variant get string function auto cast null to SQL NULL (#17466) --- src/query/functions/src/scalars/variant.rs | 18 +++++++++++++----- .../tests/it/scalars/testdata/variant.txt | 18 ++++++++++++++++++ .../functions/tests/it/scalars/variant.rs | 2 ++ .../02_0051_function_semi_structureds_get.test | 11 ++++++++++- 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/query/functions/src/scalars/variant.rs b/src/query/functions/src/scalars/variant.rs index 4b24871c61e87..623f40f72d43b 100644 --- a/src/query/functions/src/scalars/variant.rs +++ b/src/query/functions/src/scalars/variant.rs @@ -394,8 +394,12 @@ pub fn register(registry: &mut FunctionRegistry) { } match get_by_name(val, name, false) { Some(v) => { - let json_str = cast_to_string(&v); - output.push(&json_str); + if is_null(&v) { + output.push_null(); + } else { + let json_str = cast_to_string(&v); + output.push(&json_str); + } } None => output.push_null(), } @@ -419,8 +423,12 @@ pub fn register(registry: &mut FunctionRegistry) { } else { match get_by_index(val, idx as usize) { Some(v) => { - let json_str = cast_to_string(&v); - output.push(&json_str); + if is_null(&v) { + output.push_null(); + } else { + let json_str = cast_to_string(&v); + output.push(&json_str); + } } None => { output.push_null(); @@ -632,7 +640,7 @@ pub fn register(registry: &mut FunctionRegistry) { let mut out_offsets = Vec::new(); match get_by_path(&buf, json_path, &mut out_buf, &mut out_offsets) { Ok(()) => { - if out_offsets.is_empty() { + if out_offsets.is_empty() || is_null(&out_buf) { output.push_null(); } else { let json_str = cast_to_string(&out_buf); diff --git a/src/query/functions/tests/it/scalars/testdata/variant.txt b/src/query/functions/tests/it/scalars/testdata/variant.txt index 423818b9d6fcc..c075db81eaf17 100644 --- a/src/query/functions/tests/it/scalars/testdata/variant.txt +++ b/src/query/functions/tests/it/scalars/testdata/variant.txt @@ -900,6 +900,15 @@ output domain : {"{\"b\":2}"..="{\"b\":2}"} output : '{"b":2}' +ast : json_extract_path_text('{"a":null}', 'a') +raw expr : json_extract_path_text('{"a":null}', 'a') +checked expr : json_extract_path_text("{\"a\":null}", "a") +optimized expr : NULL +output type : String NULL +output domain : {NULL} +output : NULL + + ast : json_extract_path_text(s, k) raw expr : json_extract_path_text(s::String, k::String) checked expr : json_extract_path_text(s, k) @@ -3283,6 +3292,15 @@ output domain : {NULL} output : NULL +ast : parse_json('{"k":null}')->>'k' +raw expr : get_string(parse_json('{"k":null}'), 'k') +checked expr : get_string(parse_json("{\"k\":null}"), "k") +optimized expr : NULL +output type : String NULL +output domain : {NULL} +output : NULL + + ast : CAST(('a', 'b') AS VARIANT)->>'2' raw expr : get_string(CAST(tuple('a', 'b') AS Variant), '2') checked expr : get_string(to_variant(tuple("a", "b")), "2") diff --git a/src/query/functions/tests/it/scalars/variant.rs b/src/query/functions/tests/it/scalars/variant.rs index 0ebd068b23f85..c172d1dc2ddd8 100644 --- a/src/query/functions/tests/it/scalars/variant.rs +++ b/src/query/functions/tests/it/scalars/variant.rs @@ -326,6 +326,7 @@ fn test_get_string_arrow_op(file: &mut impl Write) { run_ast(file, "parse_json('[1,2,3,4]')->>(2+3)", &[]); run_ast(file, "parse_json('{\"k\":\"v\"}')->>'k'", &[]); run_ast(file, "parse_json('{\"k\":\"v\"}')->>'x'", &[]); + run_ast(file, "parse_json('{\"k\":null}')->>'k'", &[]); run_ast(file, "CAST(('a', 'b') AS VARIANT)->>'2'", &[]); run_ast(file, "parse_json(s)->>i", &[ @@ -471,6 +472,7 @@ fn test_json_extract_path_text(file: &mut impl Write) { ); run_ast(file, "json_extract_path_text('{\"a\":{\"b\":2}}', 'a')", &[ ]); + run_ast(file, "json_extract_path_text('{\"a\":null}', 'a')", &[]); run_ast(file, "json_extract_path_text(s, k)", &[ ( diff --git a/tests/sqllogictests/suites/query/functions/02_0051_function_semi_structureds_get.test b/tests/sqllogictests/suites/query/functions/02_0051_function_semi_structureds_get.test index be5f0cffdd183..80820b5fe56ae 100644 --- a/tests/sqllogictests/suites/query/functions/02_0051_function_semi_structureds_get.test +++ b/tests/sqllogictests/suites/query/functions/02_0051_function_semi_structureds_get.test @@ -92,13 +92,18 @@ NULL query T select parse_json('{"aa": null, "aA": 2, "Aa": 3}')->>'aa' ---- -null +NULL query T select parse_json(null)->>'aa' ---- NULL +query T +select parse_json('{"key1":null}')->>'key1' +---- +NULL + query T select parse_json('[2.71, 3.14]')[0] ---- @@ -201,6 +206,10 @@ select json_extract_path_text('{"customer":{"id": 1, "name":"databend", "extras" ---- {"customer":{"extras":["ext","test"],"id":1,"name":"databend"}} +query T +select json_extract_path_text('{"attr":null}', 'attr') +---- +NULL query T select NULL#>'{0}'