Description:
When querying a TIME field that is set to 00:00:00, mysql.connector throws an exception when trying to unpack the result.
According to https://dev.mysql.com/doc/internals/en/binary-protocol-value.html:
to save space the packet can be compressed:
if year, month, day, hour, minutes, seconds and micro_seconds are all 0, length is 0 and no other field is sent
How to repeat:
Here is my sample program:
#!venv/bin/python3
import mysql.connector
def q(query):
cursor = dbh.cursor(prepared=True)
cursor.execute(query)
for row in cursor:
print(f"row = {row}")
dbh = mysql.connector.connect(user="shier", database="test")
q("create temporary table a(b time)")
q("insert into a set b='00:00'")
q("select * from a")
Here is the result:
Traceback (most recent call last):
File "./b.py", line 14, in <module>
q("select * from a")
File "./b.py", line 8, in q
for row in cursor:
File "/home/shier/public_html/dxscripts/venv/lib64/python3.6/site-packages/mysql/connector/cursor.py", line 1192, in fetchone
return self._fetch_row() or None
File "/home/shier/public_html/dxscripts/venv/lib64/python3.6/site-packages/mysql/connector/cursor.py", line 837, in _fetch_row
binary=self._binary, columns=self.description)
File "/home/shier/public_html/dxscripts/venv/lib64/python3.6/site-packages/mysql/connector/connection.py", line 421, in get_row
(rows, eof) = self.get_rows(count=1, binary=binary, columns=columns)
File "/home/shier/public_html/dxscripts/venv/lib64/python3.6/site-packages/mysql/connector/connection.py", line 441, in get_rows
self._socket, columns, count)
File "/home/shier/public_html/dxscripts/venv/lib64/python3.6/site-packages/mysql/connector/protocol.py", line 476, in read_binary_result
values = self._parse_binary_values(columns, packet[5:])
File "/home/shier/public_html/dxscripts/venv/lib64/python3.6/site-packages/mysql/connector/protocol.py", line 448, in _parse_binary_values
(packet, value) = self._parse_binary_time(packet, field)
File "/home/shier/public_html/dxscripts/venv/lib64/python3.6/site-packages/mysql/connector/protocol.py", line 413, in _parse_binary_time
days = struct_unpack('I', data[1:5])[0]
Suggested fix:
Here is a patch that fixes the problem:
diff --git a/mysql/connector/protocol.py b/mysql/connector/protocol.py
index 0ce9cfb..fc465ad 100644
--- a/mysql/connector/protocol.py
+++ b/mysql/connector/protocol.py
@@ -406,6 +406,8 @@ class MySQLProtocol(object):
def _parse_binary_time(self, packet, field):
"""Parse a time value from a binary packet"""
length = packet[0]
+ if length == 0:
+ return (packet[1:], datetime.timedelta())
data = packet[1:length + 1]
mcs = 0
if length > 8: