Bug #118208 Using get_warnings causes out of sync error when executing multiple statements
Submitted: 15 May 16:48 Modified: 19 May 8:42
Reporter: Austin Dexter Email Updates:
Status: Verified Impact on me:
None 
Category:Connector / Python Severity:S3 (Non-critical)
Version:mysql-connector 9.3.0 OS:Any
Assigned to: CPU Architecture:Any

[15 May 16:48] Austin Dexter
Description:
When running multiple queries at once via cursor.execute while the connection has get_warnings=True, certain combinations of queries cause a "Commands out of sync; you can't run this command now" error even when results are being fetched correctly. This seems to happen when a warning is generated in the middle of the statements. It does not matter if the results are being handled via cursor.fetchsets, cursor.fetchall & cursor.nextset(), etc.

As an example, these three statements will generate a warning for the "DROP TABLE IF EXISTS..." portion assuming the table doesn't exist:

"SELECT TRUE; DROP TABLE IF EXISTS foo; SELECT FALSE;"

The next execute statement will receive an 'commands out of sync' error even if the results of each statement are properly handled. This is only true if the 'get_warnings' argument is True; if False, it works as expected.

Swapping the order of the commands so the statement generating the warning occurs last works fine with get_warnings on and off:

"SELECT TRUE; SELECT FALSE; DROP TABLE IF EXISTS foo;"

This allows the result sets to be handled properly and subsequent execute statements to proceed as normal.

This is using MySQL 8.0.32, Python 3.9.18, and mysql-connector-python 9.3.0.

How to repeat:
connection = mysql.connector.connect(
                host=host,
                user=user,
                passwd=passwd,
                database=db,
                connection_timeout=10000,
                allow_local_infile=True,
                raise_on_warnings=False,
                autocommit=True,
                get_warnings=True,
            )

cur = connection.cursor(
                buffered=True,
            )
# Works
sql = "SELECT TRUE; SELECT FALSE; DROP TABLE IF EXISTS foo;"

cur.execute(sql, map_results=True)

for statement, result_set in cur.fetchsets():
    print(statement)
    print(result_set)

# Does not work
sql = "SELECT TRUE; DROP TABLE IF EXISTS foo; SELECT FALSE;"

cur.execute(sql, map_results=True)

for statement, result_set in cur.fetchsets():
    print(statement)
    print(result_set)
[19 May 8:42] MySQL Verification Team
Hello Austin Dexter,

Thank you for the report and test case.

regards,
Umesh