Bug #98943 | Procedure returns incorrect result on second invocation | ||
---|---|---|---|
Submitted: | 13 Mar 2020 12:28 | Modified: | 16 Mar 2020 13:03 |
Reporter: | Damjan Vujnovic | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: Stored Routines | Severity: | S2 (Serious) |
Version: | 8.0.19 | OS: | Linux |
Assigned to: | CPU Architecture: | x86 |
[13 Mar 2020 12:28]
Damjan Vujnovic
[13 Mar 2020 12:51]
MySQL Verification Team
Thank you for the bug report. Which is the correct result you expect?
[13 Mar 2020 12:52]
Damjan Vujnovic
This is what should happen (and happens first time): mysql> call check_game(); +------+ | true | +------+ | 1 | +------+ 1 row in set (0.00 sec) This is what happens instead: mysql> call check_game(); Empty set (0.00 sec)
[13 Mar 2020 13:16]
MySQL Verification Team
Here the result on Windows: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 10 Server version: 8.0.19 MySQL Community Server - GPL Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> USE test Database changed mysql> create table game( -> game_id varchar(255) primary key, -> document json -> ); Query OK, 0 rows affected (0.05 sec) mysql> mysql> insert into game values ( -> 'test', -> '{ '> "prize": [{"up": 19, "down": 20}, {"up": 1, "down": 20}], '> "total": 10 '> }' -> ); Query OK, 1 row affected (0.01 sec) mysql> drop procedure if exists check_game; Query OK, 0 rows affected, 1 warning (0.01 sec) mysql> create procedure check_game() -> select true -> from -> game, -> json_table( -> document, -> '$.prize[*]' columns( -> up bigint path '$.up', -> down bigint path '$.down' -> ) -> ) p -> where game_id = 'test' -> and floor(json_extract(document, '$.total') * up / down) <> (json_extract(document, '$.total') * up / down) -> limit 1; Query OK, 0 rows affected (0.01 sec) mysql> call check_game(); +------+ | true | +------+ | 1 | +------+ 1 row in set (0.01 sec) Query OK, 0 rows affected (0.01 sec) mysql> call check_game(); +------+ | true | +------+ | 1 | +------+ 1 row in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql> call check_game(); +------+ | true | +------+ | 1 | +------+ 1 row in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql> call check_game(); +------+ | true | +------+ | 1 | +------+ 1 row in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql> call check_game(); +------+ | true | +------+ | 1 | +------+ 1 row in set (0.00 sec) Query OK, 0 rows affected (0.01 sec) mysql> call check_game(); +------+ | true | +------+ | 1 | +------+ 1 row in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql> call check_game(); +------+ | true | +------+ | 1 | +------+ 1 row in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql> call check_game(); +------+ | true | +------+ | 1 | +------+ 1 row in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql>
[13 Mar 2020 13:21]
MySQL Verification Team
Not repeatable on Linux too: mysql 8.0 > create procedure check_game() -> select true -> from -> game, -> json_table( -> document, -> '$.prize[*]' columns( -> up bigint path '$.up', -> down bigint path '$.down' -> ) -> ) p -> where game_id = 'test' -> and floor(json_extract(document, '$.total') * up / down) <> (json_extract(document, '$.total') * up / down) -> limit 1; Query OK, 0 rows affected (0,30 sec) mysql 8.0 > call check_game(); +------+ | true | +------+ | 1 | +------+ 1 row in set (0,01 sec) Query OK, 0 rows affected (0,01 sec) mysql 8.0 > call check_game(); +------+ | true | +------+ | 1 | +------+ 1 row in set (0,00 sec) Query OK, 0 rows affected (0,00 sec) mysql 8.0 > call check_game(); +------+ | true | +------+ | 1 | +------+ 1 row in set (0,00 sec) Query OK, 0 rows affected (0,00 sec) mysql 8.0 > call check_game(); +------+ | true | +------+ | 1 | +------+ 1 row in set (0,00 sec) Query OK, 0 rows affected (0,00 sec) mysql 8.0 > call check_game(); +------+ | true | +------+ | 1 | +------+ 1 row in set (0,00 sec) Query OK, 0 rows affected (0,00 sec) mysql 8.0 > call check_game(); +------+ | true | +------+ | 1 | +------+ 1 row in set (0,00 sec) Query OK, 0 rows affected (0,00 sec) mysql 8.0 > call check_game(); +------+ | true | +------+ | 1 | +------+ 1 row in set (0,00 sec) Query OK, 0 rows affected (0,00 sec) mysql 8.0 > call check_game(); +------+ | true | +------+ | 1 | +------+ 1 row in set (0,00 sec) Query OK, 0 rows affected (0,00 sec) mysql 8.0 > SHOW VARIABLES LIKE "%VERSION%"; +--------------------------+----------------------------------------+ | Variable_name | Value | +--------------------------+----------------------------------------+ | immediate_server_version | 999999 | | innodb_version | 8.0.20 | | original_server_version | 999999 | | protocol_version | 10 | | slave_type_conversions | | | tls_version | TLSv1,TLSv1.1,TLSv1.2,TLSv1.3 | | version | 8.0.20 | | version_comment | Source distribution BUILT: 2020-FEB-10 | | version_compile_machine | x86_64 | | version_compile_os | Linux | | version_compile_zlib | 1.2.11 | +--------------------------+----------------------------------------+ 11 rows in set (0,04 sec) mysql 8.0 >
[13 Mar 2020 13:34]
Damjan Vujnovic
Interesting :) thank you. I’ve noticed you’re using dev (8.0.20) build on Linux, how about GA (8.0.19)? Thanks again for your help, damjan
[13 Mar 2020 13:53]
MySQL Verification Team
Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 8 Server version: 8.0.19 MySQL Community Server - GPL Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> CREATE DATABASE test; Query OK, 1 row affected (0,15 sec) mysql> USE test; Database changed mysql> create table game( -> game_id varchar(255) primary key, -> document json -> ); Query OK, 0 rows affected (0,73 sec) mysql> insert into game values ( -> 'test', -> '{ '> "prize": [{"up": 19, "down": 20}, {"up": 1, "down": 20}], '> "total": 10 '> }' -> ); Query OK, 1 row affected (0,12 sec) mysql> drop procedure if exists check_game; from game, json_table( Query OK, 0 rows affected, 1 warning (0,05 sec) mysql> create procedure check_game() -> select true -> from -> game, -> json_table( -> document, -> '$.prize[*]' columns( -> up bigint path '$.up', -> down bigint path '$.down' -> ) -> ) p -> where game_id = 'test' -> and floor(json_extract(document, '$.total') * up / down) <> (json_extract(document, '$.total') * up / down) -> limit 1; Query OK, 0 rows affected (0,16 sec) mysql> call check_game(); +------+ | true | +------+ | 1 | +------+ 1 row in set (0,00 sec) Query OK, 0 rows affected (0,00 sec) mysql> call check_game(); +------+ | true | +------+ | 1 | +------+ 1 row in set (0,00 sec) Query OK, 0 rows affected (0,00 sec) mysql> call check_game(); +------+ | true | +------+ | 1 | +------+ 1 row in set (0,01 sec) Query OK, 0 rows affected (0,01 sec) mysql> call check_game(); +------+ | true | +------+ | 1 | +------+ 1 row in set (0,00 sec) Query OK, 0 rows affected (0,00 sec) mysql> call check_game(); +------+ | true | +------+ | 1 | +------+ 1 row in set (0,00 sec) Query OK, 0 rows affected (0,00 sec) mysql> call check_game(); +------+ | true | +------+ | 1 | +------+ 1 row in set (0,00 sec) Query OK, 0 rows affected (0,00 sec) mysql> SHOW VARIABLES LIKE "%VERSION%"; +--------------------------+-------------------------------+ | Variable_name | Value | +--------------------------+-------------------------------+ | immediate_server_version | 999999 | | innodb_version | 8.0.19 | | original_server_version | 999999 | | protocol_version | 10 | | slave_type_conversions | | | tls_version | TLSv1,TLSv1.1,TLSv1.2,TLSv1.3 | | version | 8.0.19 | | version_comment | MySQL Community Server - GPL | | version_compile_machine | x86_64 | | version_compile_os | linux-glibc2.12 | | version_compile_zlib | 1.2.11 | +--------------------------+-------------------------------+ 11 rows in set (0,00 sec) mysql>
[13 Mar 2020 14:20]
MySQL Verification Team
Hi Mr. Vujnovic, I was also unable to repeat your problem with 8.0.19: +------+ | true | +------+ | 1 | +------+ 1 row in set (0.00 sec) +------+ | true | +------+ | 1 | +------+ 1 row in set (0.00 sec) +------+ | true | +------+ | 1 | +------+ 1 row in set (0.00 sec)+------+ | true | +------+ | 1 | +------+ 1 row in set (0.00 sec)+------+ | true | +------+ | 1 | +------+ 1 row in set (0.00 sec) +------+ | true | +------+ | 1 | +------+ 1 row in set (0.00 sec) +------+ | true | +------+ | 1 | +------+ 1 row in set (0.00 sec) and so on .....
[13 Mar 2020 14:40]
Damjan Vujnovic
Thank you all for your help. I've just spun a MySQL instance on AWS and tried my little script, and (as I've feared) it does not behave incorrectly :( However, all our workstations and dev/prod instances (mix of macOS and Centos) misbehave. It could be related to the rest of the schema, so I guess my next step is to see if I could produce enough of the schema to trigger it 'from scratch'... Which might be a problem for us (openly publishing DB schema). Is there a way for us to send it through some other channel? Many thanks again for your help and wish you a great weekend, damjan
[13 Mar 2020 14:43]
MySQL Verification Team
Damjan, You are truly welcome !!!
[13 Mar 2020 17:22]
Damjan Vujnovic
Apologies - I just went again over everything and it turns out that on the environments and workstationss with this issue the MySQL version was 8.0.17. I then tried running the above script on clean 8.0.17 installations and the problem does indeed occur. I then upgraded to 8.0.18 and the issue persisted. After the upgrade to 8.0.19 the problem went away... I then tried checking the 8.0.19 changelog and couldn't see anything related, so I just hope it wasn't fixed "by accident"... Were you aware of this issue prior to 8.0.19? Many thanks again and wish you all a great weekend, damjan
[13 Mar 2020 17:27]
Damjan Vujnovic
Actually, I've found it: JSON: If the first argument to JSON_TABLE() was const during the execution of a stored procedure, but not during preparation, it was not re-evaluated when a statement was subsequently executed again, causing an empty result to be returned each time following the first execution of the procedure. (Bug #97097, Bug #30382156) Feel free to close this one.
[16 Mar 2020 13:03]
MySQL Verification Team
Thank you, Mr. Vujnovic.
[14 Jan 10:21]
DK Singh
Hi @Damjan Vujnovic While I'm using 8.0.32 and same issue I'm facing. I'm not using any Json_Table or Temporary Table and all. When I execute the query outside the stored proc it gives me correct result every time but from stored proc gives me correct result only first time
[14 Jan 11:42]
MySQL Verification Team
Thank you Mr. Singh.