Skip to content

Commit 955cfb7

Browse files
committed
BUG20407036: Fix incorrect arguments to mysld_stmt_execute error
Inserting a string of length 251 to 255 using prepared statements was raising a ProgrammingError exception: 1210 (HY000): Incorrect arguments to mysqld_stmt_execute We fix this by correctly encoding the length of the string while sending it to the server. A test case has been added for BUG#20407036.
1 parent 5530b47 commit 955cfb7

File tree

3 files changed

+52
-8
lines changed

3 files changed

+52
-8
lines changed

lib/mysql/connector/utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# MySQL Connector/Python - MySQL driver written in Python.
2-
# Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
2+
# Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
33

44
# MySQL Connector/Python is licensed under the terms of the GPLv2
55
# <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
@@ -144,7 +144,7 @@ def lc_int(i):
144144
if i < 0 or i > 18446744073709551616:
145145
raise ValueError('Requires 0 <= i <= 2^64')
146146

147-
if i <= 255:
147+
if i < 251:
148148
return bytearray(struct.pack('<B', i))
149149
elif i <= 65535:
150150
return b'\xfc' + bytearray(struct.pack('<H', i))

tests/test_bugs.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: utf-8 -*-
22
# MySQL Connector/Python - MySQL driver written in Python.
3-
# Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
3+
# Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
44

55
# MySQL Connector/Python is licensed under the terms of the GPLv2
66
# <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
@@ -3292,3 +3292,47 @@ def test_warning_with_rows(self):
32923292
self.assertEqual(exp, cur.stored_results().next().fetchall())
32933293
exp = [(u'Warning', 1642, u'TEST WARNING')]
32943294
self.assertEqual(exp, cur.fetchwarnings())
3295+
3296+
3297+
class BugOra20407036(tests.MySQLConnectorTests):
3298+
"""BUG#20407036: INCORRECT ARGUMENTS TO MYSQLD_STMT_EXECUTE ERROR
3299+
"""
3300+
def setUp(self):
3301+
config = tests.get_mysql_config()
3302+
self.cnx = connection.MySQLConnection(**config)
3303+
self.cur = self.cnx.cursor()
3304+
3305+
self.tbl = 'Bug20407036'
3306+
self.cur.execute("DROP TABLE IF EXISTS {0}".format(self.tbl))
3307+
3308+
create = ("CREATE TABLE {0} ( id int(10) unsigned NOT NULL, "
3309+
"text VARCHAR(70000) CHARACTER SET utf8 NOT NULL, "
3310+
"rooms tinyint(3) unsigned NOT NULL) "
3311+
"ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 "
3312+
"COLLATE=utf8_unicode_ci".format(self.tbl))
3313+
self.cur.execute(create)
3314+
3315+
def tearDown(self):
3316+
self.cur.execute("DROP TABLE IF EXISTS {0}".format(self.tbl))
3317+
self.cur.close()
3318+
self.cnx.close()
3319+
3320+
def test_binary_charset(self):
3321+
cur = self.cnx.cursor(prepared=True)
3322+
sql = "INSERT INTO {0}(text, rooms) VALUES(%s, %s)".format(self.tbl)
3323+
cur.execute(sql, ('a'*252, 1))
3324+
cur.execute(sql, ('a'*253, 2))
3325+
cur.execute(sql, ('a'*255, 3))
3326+
cur.execute(sql, ('a'*251, 4))
3327+
cur.execute(sql, ('a'*65535, 5))
3328+
3329+
exp = [
3330+
(0, 'a'*252, 1),
3331+
(0, 'a'*253, 2),
3332+
(0, 'a'*255, 3),
3333+
(0, 'a'*251, 4),
3334+
(0, 'a'*65535, 5),
3335+
]
3336+
3337+
self.cur.execute("SELECT * FROM {0}".format(self.tbl))
3338+
self.assertEqual(exp, self.cur.fetchall())

tests/test_utils.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# MySQL Connector/Python - MySQL driver written in Python.
2-
# Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
2+
# Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
33

44
# MySQL Connector/Python is licensed under the terms of the GPLv2
55
# <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
@@ -125,12 +125,12 @@ def test_intstore(self):
125125

126126
def test_lc_int(self):
127127
prefix = (b'', b'\xfc', b'\xfd', b'\xfe')
128+
intstore = (1, 2, 3, 8)
128129
try:
129-
for i, j in enumerate((8, 16, 24, 64)):
130-
val = 2 ** (j - 1)
131-
lenenc = utils.lc_int(val)
130+
for i, j in enumerate((128, 251, 2**24-1, 2**64-1)):
131+
lenenc = utils.lc_int(j)
132132
exp = prefix[i] + \
133-
getattr(utils, 'int{0}store'.format(int(j/8)))(val)
133+
getattr(utils, 'int{0}store'.format(intstore[i]))(j)
134134
self.assertEqual(exp, lenenc)
135135
except ValueError as err:
136136
self.fail("length_encoded_int failed for size {0}".format(j, err))

0 commit comments

Comments
 (0)