diff --git a/extension/json/include/json_executors.hpp b/extension/json/include/json_executors.hpp index 167666b4d636..27c174e5a60a 100644 --- a/extension/json/include/json_executors.hpp +++ b/extension/json/include/json_executors.hpp @@ -140,8 +140,9 @@ struct JSONExecutors { auto mut_ldoc = yyjson_doc_mut_copy(ldoc, alc); auto new_val = fun(mut_ldoc->root, mut_ldoc, right, alc, result); + ldoc = yyjson_mut_val_imut_copy(new_val, alc); - return JSONCommon::WriteVal(new_val, alc); + return JSONCommon::WriteVal(ldoc->root, alc); }); } diff --git a/extension/json/json_functions/json_array_append.cpp b/extension/json/json_functions/json_array_append.cpp index 51b0a63b6642..a5f10488748d 100644 --- a/extension/json/json_functions/json_array_append.cpp +++ b/extension/json/json_functions/json_array_append.cpp @@ -14,7 +14,9 @@ static void ArrayAppendFunction(DataChunk &args, ExpressionState &state, Vector JSONExecutors::BinaryMutExecute( args, state, result, [](yyjson_mut_val *arr, yyjson_mut_doc *doc, string_t element, yyjson_alc *alc, Vector &result) { - D_ASSERT(yyjson_mut_is_arr(arr)); + if (!yyjson_mut_is_arr(arr)) { + throw InvalidInputException("JSON input not an JSON Array"); + } auto edoc = JSONCommon::ReadDocument(element, JSONCommon::READ_FLAG, alc); auto mut_edoc = yyjson_doc_mut_copy(edoc, alc); @@ -28,7 +30,9 @@ static void ArrayAppendFunction(DataChunk &args, ExpressionState &state, Vector JSONExecutors::BinaryMutExecute( args, state, result, [&](yyjson_mut_val *arr, yyjson_mut_doc *doc, bool element, yyjson_alc *alc, Vector &result) { - D_ASSERT(yyjson_mut_is_arr(arr)); + if (!yyjson_mut_is_arr(arr)) { + throw InvalidInputException("JSON input not a JSON Array"); + } yyjson_mut_arr_add_bool(doc, arr, element); return arr; @@ -40,21 +44,25 @@ static void ArrayAppendFunction(DataChunk &args, ExpressionState &state, Vector JSONExecutors::BinaryMutExecute( args, state, result, [&](yyjson_mut_val *arr, yyjson_mut_doc *doc, int64_t el, yyjson_alc *alc, Vector &result) { - D_ASSERT(yyjson_mut_is_arr(arr)); + if (!yyjson_mut_is_arr(arr)) { + throw InvalidInputException("JSON input not a JSON Array"); + } - int64_t element = static_cast(el); + int64_t element = static_cast(el); - yyjson_mut_arr_add_int(doc, arr, element); - return arr; + yyjson_mut_arr_add_int(doc, arr, element); + return arr; }); // Floating value } else if (right_type == LogicalType::FLOAT || right_type == LogicalType::DOUBLE) { JSONExecutors::BinaryMutExecute( args, state, result, [&](yyjson_mut_val *arr, yyjson_mut_doc *doc, double el, yyjson_alc *alc, Vector &result) { - D_ASSERT(yyjson_mut_is_arr(arr)); + if (!yyjson_mut_is_arr(arr)) { + throw InvalidInputException("JSON input not a JSON Array"); + } - double element = static_cast(el); + double element = el; yyjson_mut_arr_add_real(doc, arr, element); return arr; @@ -76,12 +84,10 @@ ScalarFunctionSet JSONFunctions::GetArrayAppendFunction() { GetArrayAppendFunctionInternal(set, JSONCommon::JSONType(), LogicalType::BOOLEAN); // Allows for Integer types - // TINYINT, SMALLINT, INTEGER, UTINYINT, USMALLINT are captured by BIGINT + // TINYINT, SMALLINT, INTEGER, UTINYINT, USMALLINT, UINTEGER are captured by BIGINT // relies on consistant casting strategy upfront GetArrayAppendFunctionInternal(set, LogicalType::VARCHAR, LogicalType::BIGINT); GetArrayAppendFunctionInternal(set, JSONCommon::JSONType(), LogicalType::BIGINT); - GetArrayAppendFunctionInternal(set, LogicalType::VARCHAR, LogicalType::UINTEGER); - GetArrayAppendFunctionInternal(set, JSONCommon::JSONType(), LogicalType::UINTEGER); GetArrayAppendFunctionInternal(set, LogicalType::VARCHAR, LogicalType::UBIGINT); GetArrayAppendFunctionInternal(set, JSONCommon::JSONType(), LogicalType::UBIGINT); diff --git a/test/sql/json/scalar/test_json_array_append.test b/test/sql/json/scalar/test_json_array_append.test new file mode 100644 index 000000000000..1a93559e105b --- /dev/null +++ b/test/sql/json/scalar/test_json_array_append.test @@ -0,0 +1,135 @@ +# name: test/sql/json/scalar/test_json_array_append.test +# description: Checks whether a given JSON Array is appended correctly +# group: [scalar] + +require json + +statement ok +PRAGMA enable_verification + +# list with varchar to json +statement ok +create table test (j json) + +statement ok +insert into test values('[]'), ('[42]'), ('["a", 42, true]') + +query I +SELECT json_array_append(json_array_append(j, True), False) FROM test +---- +[true,false] +[42,true,false] +["a",42,true,true,false] + +query I +SELECT json_array_append(j, 42::UTINYINT) FROM test +---- +[42] +[42,42] +["a",42,true,42] + +query I +SELECT json_array_append(json_array_append(j, -42::TINYINT), 42::TINYINT) FROM test +---- +[-42,42] +[42,-42,42] +["a",42,true,-42,42] + +query I +SELECT json_array_append(j, 1337::USMALLINT) FROM test +---- +[1337] +[42,1337] +["a",42,true,1337] + +query I +SELECT json_array_append(json_array_append(j, -1337::SMALLINT), 1337::SMALLINT) FROM test +---- +[-1337,1337] +[42,-1337,1337] +["a",42,true,-1337,1337] + +query I +SELECT json_array_append(j, 2024::UINTEGER) FROM test +---- +[2024] +[42,2024] +["a",42,true,2024] + +query I +SELECT json_array_append(json_array_append(j, -2024::INTEGER), 2024::INTEGER) FROM test +---- +[-2024,2024] +[42,-2024,2024] +["a",42,true,-2024,2024] + +query I +SELECT json_array_append(j, 1234567891011121314::UBIGINT) FROM test +---- +[1234567891011121314] +[42,1234567891011121314] +["a",42,true,1234567891011121314] + +query I +SELECT json_array_append(json_array_append(j, -1234567891011121314::BIGINT), 1234567891011121314::BIGINT) FROM test +---- +[-1234567891011121314,1234567891011121314] +[42,-1234567891011121314,1234567891011121314] +["a",42,true,-1234567891011121314,1234567891011121314] + +query I +SELECT json_array_append(json_array_append(j, pi()::FLOAT), pi()::DOUBLE) FROM test +---- +[3.1415927410125732,3.141592653589793] +[42,3.1415927410125732,3.141592653589793] +["a",42,true,3.1415927410125732,3.141592653589793] + +statement ok +create table test2 (j json) + +statement ok +insert into test2 values('42'), ('"Hello"'), ('true'), ('[1337]'), ('{"a": 42}') + +query I +SELECT json_array_append(a.j, b.j) FROM test AS a, test2 AS b +---- +[42] +["Hello"] +[true] +[[1337]] +[{"a":42}] +[42,42] +[42,"Hello"] +[42,true] +[42,[1337]] +[42,{"a":42}] +["a",42,true,42] +["a",42,true,"Hello"] +["a",42,true,true] +["a",42,true,[1337]] +["a",42,true,{"a":42}] + +statement error +SELECT json_array_append('', False) +--- +Error: Invalid Input Error: Malformed JSON at byte 0 of input: input length is 0. Input: + +statement error +SELECT json_array_append('{}', False) +--- +Error: Invalid Input Error: JSON input not a JSON Array + +statement error +SELECT json_array_append('true', False) +--- +Error: Invalid Input Error: JSON input not a JSON Array + +statement error +SELECT json_array_append('"Hello"', False) +--- +Error: Invalid Input Error: JSON input not a JSON Array + +statement error +SELECT json_array_append('42', False) +--- +Error: Invalid Input Error: JSON input not a JSON Array