Bug #98496 | JSON columns allow empty string, allowing invalid JSON in binlog row images | ||
---|---|---|---|
Submitted: | 5 Feb 2020 20:21 | Modified: | 11 Sep 2023 7:38 |
Reporter: | Jeremy Cole (Basic Quality Contributor) (OCA) | Email Updates: | |
Status: | Duplicate | Impact on me: | |
Category: | MySQL Server: JSON | Severity: | S3 (Non-critical) |
Version: | 5.7, 8.0 | OS: | Any |
Assigned to: | CPU Architecture: | Any | |
Tags: | binlog, empty string, json, null, RBR |
[5 Feb 2020 20:21]
Jeremy Cole
[6 Feb 2020 6:45]
MySQL Verification Team
Hi Jeremy, Thanks for the report. I appreciate the details. Verified as stated.
[7 Sep 2023 14:10]
Matt Lord
I cannot repeat the original issue, but we've run into a similar one: mysql> show global variables like "%version%"; +--------------------------+------------------------------+ | Variable_name | Value | +--------------------------+------------------------------+ | admin_tls_version | TLSv1.2,TLSv1.3 | | innodb_version | 8.0.34 | | protocol_version | 10 | | replica_type_conversions | | | slave_type_conversions | | | tls_version | TLSv1.2,TLSv1.3 | | version | 8.0.34 | | version_comment | MySQL Community Server - GPL | | version_compile_machine | arm64 | | version_compile_os | macos13 | | version_compile_zlib | 1.2.13 | +--------------------------+------------------------------+ 11 rows in set (0.00 sec) mysql> create table jstest (id int not null auto_increment primary key, json_data json not null); Query OK, 0 rows affected (0.00 sec) mysql> set session sql_mode=''; Query OK, 0 rows affected (0.00 sec) mysql> insert into jstest (id, json_data) values (1, ''); ERROR 3140 (22032): Invalid JSON text: "The document is empty." at position 0 in value for column 'jstest.json_data'. mysql> insert ignore into jstest (id, json_data) values (1, ''); ERROR 3140 (22032): Invalid JSON text: "The document is empty." at position 0 in value for column 'jstest.json_data'. mysql> insert into jstest (id, json_data) values (1, NULL); ERROR 1048 (23000): Column 'json_data' cannot be null mysql> insert ignore into jstest (id, json_data) values (1, NULL); Query OK, 1 row affected, 1 warning (0.01 sec) mysql> show warnings; +---------+------+-----------------------------------+ | Level | Code | Message | +---------+------+-----------------------------------+ | Warning | 1048 | Column 'json_data' cannot be null | +---------+------+-----------------------------------+ 1 row in set (0.00 sec) mysql> select * from jstest; +----+-----------+ | id | json_data | +----+-----------+ | 1 | null | +----+-----------+ 1 row in set (0.00 sec) In this case the error is converted to a warning and it's inserting a literal string 'null' which is not a valid JSON document. One could argue that this is how old MySQL / non-strict mode could be expected to work (allowing invalid data) with INSERT IGNORE: https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html#ignore-effect-on-execution BUT, using an invalid implicit default for the column/type here seems like a bug to me. I would expect a valid "empty" value to be used which in the case of JSON would be '{}' rather than 'null'. Would you prefer that I open a new bug report for this? Or do you feel it's NOT a bug for some reason? Thanks!
[8 Sep 2023 9:20]
Knut Anders Hatlen
Hi Matt, 'null' is not an invalid JSON value. The JSON specification allows three literals: true, false and null. Whether 'null' or '{}' is the best value to use for this case, can of course be argued, but using 'null' is not causing non-JSON data to be inserted into the table, as you seem to think.
[8 Sep 2023 13:47]
Matt Lord
Hi Knut! Thank you for the response. I can see that you are correct. From https://www.rfc-editor.org/rfc/rfc8259 : 3. Values A JSON value MUST be an object, array, number, or string, or one of the following three literal names: false null true The literal names MUST be lowercase. No other literal names are allowed. And this is already supported in Vitess' vtgate: mysql> create table jsontest (id int not null auto_increment primary key, json_data json not null); Query OK, 0 rows affected (0.03 sec) mysql> insert into jsontest (json_data) values ('null'); Query OK, 1 row affected (0.00 sec) mysql> insert into jsontest (json_data) values ('true'); Query OK, 1 row affected (0.01 sec) mysql> insert into jsontest (json_data) values ('false'); Query OK, 1 row affected (0.01 sec) mysql> insert into jsontest (json_data) values ('nil'); ERROR 3140 (22032): target: commerce.0.primary: vttablet: rpc error: code = Unknown desc = Invalid JSON text: "Invalid value." at position 1 in value for column 'jsontest.json_data'. (errno 3140) (sqlstate 22032) (CallerID: userData1): Sql: "insert into jsontest(json_data) values (:vtg1 /* VARCHAR */)", BindVars: {vtg1: "type:VARCHAR value:\"nil\""} Thanks again! P.S. Could this bug be closed then? At least I didn't seem able to repeat it. Perhaps I was missing something though.
[11 Sep 2023 7:38]
Knut Anders Hatlen
As far as I can tell, the problem with the binlog and the table disagreeing was fixed in bug#87734. I see 'null' reported by mysqlbinlog too now. So I assume it's OK to close it, yes. Done. Thanks.