From 8500024cb7dc432a75004b4b90f940f521f02c84 Mon Sep 17 00:00:00 2001 From: Varun Deep Saini Date: Sun, 22 Feb 2026 18:40:19 +0530 Subject: [PATCH] MDEV-38873 json_extract returns NULL through derived table json_extract() passes its result through json_nice() with LOOSE format, which can expand the output by adding spaces after commas and colons. The max_length was not accounting for this expansion, causing derived tables to truncate the result and the outer json_extract() to fail with "Unexpected end of JSON text". Fix by multiplying max_length by 2 to match JSON_FORMAT(LOOSE). Signed-off-by: Varun Deep Saini --- mysql-test/main/func_json.result | 12 ++++++++++++ mysql-test/main/func_json.test | 9 +++++++++ sql/item_jsonfunc.cc | 7 ++++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/func_json.result b/mysql-test/main/func_json.result index a549cb73291e0..b68d73c0f5e5a 100644 --- a/mysql-test/main/func_json.result +++ b/mysql-test/main/func_json.result @@ -5764,4 +5764,16 @@ NULL NULL NULL NULL NULL NULL NULL NULL {"key": "value", "key2": "value2"} 1 0 0 1 0 1 1 {"key": "value", "key": "value2"} 1 0 0 1 0 0 1 DROP TABLE test_default_json; +SELECT json_extract(t.j, '$') +FROM (SELECT json_extract('["a",1]', '$') AS j) AS t; +json_extract(t.j, '$') +["a", 1] +SELECT json_extract(t.j, '$[0]') +FROM (SELECT json_extract('["a",1]', '$') AS j) AS t; +json_extract(t.j, '$[0]') +"a" +SELECT json_extract(t.j, '$') +FROM (SELECT json_extract('{"key":"value"}', '$') AS j) AS t; +json_extract(t.j, '$') +{"key": "value"} # End of 12.3 diff --git a/mysql-test/main/func_json.test b/mysql-test/main/func_json.test index 13be0f591e5ce..81801312530ed 100644 --- a/mysql-test/main/func_json.test +++ b/mysql-test/main/func_json.test @@ -4489,4 +4489,13 @@ FROM test_default_json; DROP TABLE test_default_json; +SELECT json_extract(t.j, '$') +FROM (SELECT json_extract('["a",1]', '$') AS j) AS t; + +SELECT json_extract(t.j, '$[0]') +FROM (SELECT json_extract('["a",1]', '$') AS j) AS t; + +SELECT json_extract(t.j, '$') +FROM (SELECT json_extract('{"key":"value"}', '$') AS j) AS t; + --echo # End of 12.3 diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index 62c003091d42b..3ffca3fc44e62 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -1139,7 +1139,12 @@ bool Item_json_str_multipath::fix_length_and_dec(THD *thd) bool Item_func_json_extract::fix_length_and_dec(THD *thd) { collation.set(args[0]->collation); - max_length= args[0]->max_length * (arg_count - 1); + /* + json_extract() passes its result through json_nice() with LOOSE format, + which can expand the output (e.g. adding spaces after commas and colons). + Multiply by 2 to account for this, matching JSON_FORMAT(LOOSE) behavior. + */ + max_length= args[0]->max_length * (arg_count - 1) * 2; mark_constant_paths(paths, args+1, arg_count-1); set_maybe_null();