Description:
A query which is using json function/value is working fine as individual query but not working from inside Stored procedure.
For example-
Below query is working fine-
SET @ip_jsonmessage =
'{
"Message": {
"Request": {
"QueryRequest": {
"UserDefined": {
"Userdefined1": [
"1",
"One"
],
"Userdefined2": "2"
}
}
}
}
}';
-- run directly with session var works
WITH cte AS (
SELECT j.json_key,
JSON_EXTRACT(@ip_jsonmessage, CONCAT('$.Message.Request.QueryRequest.UserDefined.', j.json_key)) AS json_value
FROM JSON_TABLE(
JSON_KEYS(@ip_jsonmessage, '$.Message.Request.QueryRequest.UserDefined'),
"$[*]"
COLUMNS(json_key TEXT PATH "$")
) j
)
SELECT t.json_key,
t.json_value
FROM cte t
WHERE JSON_TYPE(t.json_value) != 'ARRAY'
UNION ALL
SELECT t.json_key,
j.json_value
FROM cte t,
JSON_TABLE(
t.json_value,
"$[*]"
COLUMNS(json_value JSON PATH "$")
) j
WHERE JSON_TYPE(t.json_value) = 'ARRAY';
SELECT @ip_jsonmessage, JSON_PRETTY(@ip_jsonmessage);
But when using same query inside stored procedure then throwing error-
-- run EXACT same code in SP (except using input param instead of session var even though session var is passed in as input parameter) FAILS
DELIMITER $$
DROP PROCEDURE IF EXISTS test.sp_s_json;
CREATE DEFINER = 'execution'@'127.0.0.1' PROCEDURE test.sp_s_json
(
IN ip_jsonmessage JSON)
COMMENT 'Demonstrate MySQL bug'
BEGIN
WITH cte AS (
SELECT j.json_key,
JSON_EXTRACT(ip_jsonmessage, CONCAT('$.Message.Request.QueryRequest.UserDefined.', j.json_key)) AS json_value
FROM JSON_TABLE(
JSON_KEYS(ip_jsonmessage, '$.Message.Request.QueryRequest.UserDefined'),
"$[*]"
COLUMNS(json_key TEXT PATH "$")
) j
)
SELECT t.json_key,
t.json_value
FROM cte t
WHERE JSON_TYPE(t.json_value) != 'ARRAY'
UNION ALL
SELECT t.json_key,
j.json_value
FROM cte t,
JSON_TABLE(
t.json_value,
"$[*]"
COLUMNS(json_value JSON PATH "$")
) j
WHERE JSON_TYPE(t.json_value) = 'ARRAY';
SELECT ip_jsonmessage, JSON_PRETTY(ip_jsonmessage);
END$$
DELIMITER ;
CALL test.sp_s_json(@ip_jsonmessage); -- fails: SQL Error (1210): Incorrect arguments to JSON_TABLE
How to repeat:
-- Create a stored routine
-- run EXACT same code in SP (except using input param instead of session var even though session var is passed in as input parameter) FAILS
DELIMITER $$
DROP PROCEDURE IF EXISTS test.sp_s_json;
CREATE DEFINER = 'execution'@'127.0.0.1' PROCEDURE test.sp_s_json
(
IN ip_jsonmessage JSON)
COMMENT 'Demonstrate MySQL bug'
BEGIN
WITH cte AS (
SELECT j.json_key,
JSON_EXTRACT(ip_jsonmessage, CONCAT('$.Message.Request.QueryRequest.UserDefined.', j.json_key)) AS json_value
FROM JSON_TABLE(
JSON_KEYS(ip_jsonmessage, '$.Message.Request.QueryRequest.UserDefined'),
"$[*]"
COLUMNS(json_key TEXT PATH "$")
) j
)
SELECT t.json_key,
t.json_value
FROM cte t
WHERE JSON_TYPE(t.json_value) != 'ARRAY'
UNION ALL
SELECT t.json_key,
j.json_value
FROM cte t,
JSON_TABLE(
t.json_value,
"$[*]"
COLUMNS(json_value JSON PATH "$")
) j
WHERE JSON_TYPE(t.json_value) = 'ARRAY';
SELECT ip_jsonmessage, JSON_PRETTY(ip_jsonmessage);
END$$
DELIMITER ;
-- call it now to execute code
CALL test.sp_s_json(@ip_jsonmessage);
It will fails with SQL Error (1210): Incorrect arguments to JSON_TABLE
Suggested fix:
-- CAST the field used as the source for the table to force MySQL to recognize that the json_value is JSON, then it will work
DELIMITER $$
DROP PROCEDURE IF EXISTS test.sp_s_json;
CREATE DEFINER = 'execution'@'127.0.0.1' PROCEDURE test.sp_s_json
(
IN ip_jsonmessage JSON)
COMMENT 'Demonstrate MySQL bug'
BEGIN
WITH cte AS (
SELECT j.json_key,
JSON_EXTRACT(ip_jsonmessage, CONCAT('$.Message.Request.QueryRequest.UserDefined.', j.json_key)) AS json_value
FROM JSON_TABLE(
JSON_KEYS(ip_jsonmessage, '$.Message.Request.QueryRequest.UserDefined'),
"$[*]"
COLUMNS(json_key TEXT PATH "$")
) j
)
SELECT t.json_key,
t.json_value
FROM cte t
WHERE JSON_TYPE(t.json_value) != 'ARRAY'
UNION ALL
SELECT t.json_key,
j.json_value
FROM cte t,
JSON_TABLE(
CAST(t.json_value AS JSON), -- force MySQL to recognize that the json_value is JSON
"$[*]"
COLUMNS(json_value JSON PATH "$")
) j
WHERE JSON_TYPE(t.json_value) = 'ARRAY';
SELECT ip_jsonmessage, JSON_PRETTY(ip_jsonmessage);
END$$
DELIMITER ;
CALL test.sp_s_json(@ip_jsonmessage); -- works