Bug #118239 Logical Inconsistency in MySQL String Comparison with LIKE and NOT LIKE Operators
Submitted: 21 May 13:05 Modified: 29 May 13:10
Reporter: jinhui lai Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: DML Severity:S3 (Non-critical)
Version:9.3.0 OS:Ubuntu (22.04)
Assigned to: CPU Architecture:Any

[21 May 13:05] jinhui lai
Description:
When using JDBC to connect to MySQL and executing the following SQL queries, an unexpected non-empty result is returned from the intersection of two logically opposite queries, revealing a potential logic bug. The issue arises from comparing values using the LIKE and NOT LIKE operators. Specifically, the intersection between the results of t0.c0 LIKE t1.c0 and t0.c0 NOT LIKE t1.c0 should be empty by definition, yet the query returns data, indicating a flaw in how MySQL handles comparisons involving TINYTEXT and implicit type conversions.

CREATE TABLE t0(c0 TINYTEXT) ;
CREATE TABLE t1 LIKE t0;
INSERT INTO t1(c0) VALUES(16),("⓰");
INSERT INTO t0(c0) VALUES(16);
SELECT * FROM t0 STRAIGHT_JOIN t1 ON t0.c0 LIKE t1.c0; -- {16, 16}
SELECT * FROM t0 STRAIGHT_JOIN t1 ON t0.c0 NOT LIKE t1.c0; -- {16, ⓰}
SELECT * FROM t0 STRAIGHT_JOIN t1 ON t0.c0 LIKE t1.c0 
INTERSECT 
SELECT * FROM t0 STRAIGHT_JOIN t1 ON t0.c0 NOT LIKE t1.c0; -- {16, 16}

How to repeat:
python test.py,and the test.py is as follow:

import mysql.connector
from mysql.connector import Error

sql_commands = """
CREATE DATABASE IF NOT EXISTS fuzz;
USE fuzz;
DROP TABLE IF EXISTS t0, t1;
CREATE TABLE t0(c0 TINYTEXT) ;
CREATE TABLE t1 LIKE t0;
INSERT INTO t1(c0) VALUES(16),("⓰");
INSERT INTO t0(c0) VALUES(16);
SELECT * FROM t0 STRAIGHT_JOIN t1 ON t0.c0 LIKE t1.c0;
SELECT * FROM t0 STRAIGHT_JOIN t1 ON t0.c0 NOT LIKE t1.c0;
SELECT * FROM t0 STRAIGHT_JOIN t1 ON t0.c0 LIKE t1.c0 
INTERSECT 
SELECT * FROM t0 STRAIGHT_JOIN t1 ON t0.c0 NOT LIKE t1.c0;
"""

if __name__ == '__main__':
    db_config = {
        'host': 'localhost',
        'database': 'mysql',
        'user': 'root',
        'password': '1213',
        'port': 3306,
        'charset': 'utf8mb4',
        'collation': 'utf8mb4_unicode_ci'
    }
    
    try:
        connection = mysql.connector.connect(**db_config)
        
        if connection.is_connected():
            print("Connected to MySQL database")
            
            cursor = connection.cursor()
            
            try:
                for statement in sql_commands.split(';'):
                    if statement.strip():
                        cursor.execute(statement)
                        print(f"Executed: {statement}")
                        
                        if statement.strip().upper().startswith('SELECT'):
                            results = cursor.fetchall()
                            print("Query results:")
                            for row in results:
                                print(row)
            
                connection.commit()
                
            except Error as e:
                print(f"SQL execution error: {e}")
                connection.rollback()
                
            finally:
                cursor.close()
                
    except Error as e:
        print(f"Connection error: {e}")
        
    finally:
        if 'connection' in locals() and connection.is_connected():
            connection.close()
            print("Connection closed")
[21 May 13:08] jinhui lai
you can reproduce this bug by executing "python test.py"

Attachment: test.py (application/octet-stream, text), 2.04 KiB.

[29 May 13:10] MySQL Verification Team
Hello jinhui lai,

Thank you for the report and test case.

regards,
Umesh