Skip to content

Commit 0f68012

Browse files
author
Geert Vanderkelen (Oracle)
committed
Merge branch 'release-2.0.2' into master-2.0
2 parents 6d94a93 + bd21ac9 commit 0f68012

23 files changed

+525
-121
lines changed

CHANGES.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,21 @@ Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
88
Full release notes:
99
http://dev.mysql.com/doc/relnotes/connector-python/en/
1010

11+
v2.0.2
12+
======
13+
14+
- BUG19500097: Fix string decoding with binary character set
15+
- BUG19677659: Move testings of errors to internal repository
16+
- BUG19549363: Raise error when compression used with reset_session
17+
- BUG19642249: Improve errors reporting invalid sharding keys
18+
- BUG19711759: Fix Pylint issue in network module
19+
- BUG19667984: Fix converting invalid datetime values in Django backend
20+
- BUG19660283: Fix failing unit tests with MySQL server 5.7.5
21+
- BUG19584051: Fix comparison of type_code of columns for PEP-249
22+
- BUG19522948: Fix data corruption with TEXT and prepared statements
23+
- BUG19584116: Fix extra signal causing runtime error in Django
24+
25+
1126
v2.0.1
1227
======
1328

cpyint

lib/mysql/connector/connection.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ def __init__(self, *args, **kwargs):
123123
self._ssl_active = False
124124
self._auth_plugin = None
125125
self._pool_config_version = None
126+
self._compress = False
126127

127128
if len(kwargs) > 0:
128129
self.connect(**kwargs)
@@ -271,6 +272,7 @@ def config(self, **kwargs):
271272

272273
try:
273274
if config['compress']:
275+
self._compress = True
274276
self.set_client_flags([ClientFlag.COMPRESS])
275277
except KeyError:
276278
pass # Missing compress argument is OK
@@ -884,6 +886,10 @@ def cmd_change_user(self, username='', password='', database='',
884886
if self.unread_result:
885887
raise errors.InternalError("Unread result found.")
886888

889+
if self._compress:
890+
raise errors.NotSupportedError("Change user is not supported with "
891+
"compression.")
892+
887893
packet = self._protocol.make_change_user(
888894
handshake=self._handshake,
889895
username=username, password=password, database=database,
@@ -943,8 +949,13 @@ def reset_session(self, user_variables=None, session_variables=None):
943949
try:
944950
self.cmd_reset_connection()
945951
except errors.NotSupportedError:
946-
self.cmd_change_user(self._user, self._password,
947-
self._database, self._charset_id)
952+
if self._compress:
953+
raise errors.NotSupportedError(
954+
"Reset session is not supported with compression for "
955+
"MySQL server version 5.7.2 or earlier.")
956+
else:
957+
self.cmd_change_user(self._user, self._password,
958+
self._database, self._charset_id)
948959

949960
cur = self.cursor()
950961
if user_variables:
@@ -1135,7 +1146,7 @@ def python_charset(self):
11351146
Returns a string.
11361147
"""
11371148
encoding = CharacterSet.get_info(self._charset_id)[0]
1138-
if encoding == 'utf8mb4':
1149+
if encoding in ('utf8mb4', 'binary'):
11391150
return 'utf8'
11401151
else:
11411152
return encoding

lib/mysql/connector/conversion.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,15 @@ def _str_to_mysql(self, value):
178178

179179
def _unicode_to_mysql(self, value):
180180
"""Convert unicode"""
181-
encoded = value.encode(self.charset)
182-
if self.charset_id in CharacterSet.slash_charsets:
181+
charset = self.charset
182+
charset_id = self.charset_id
183+
if charset == 'binary':
184+
charset = 'utf8'
185+
charset_id = CharacterSet.get_charset_info(charset)[0]
186+
encoded = value.encode(charset)
187+
if charset_id in CharacterSet.slash_charsets:
183188
if b'\x5c' in encoded:
184-
return HexLiteral(value, self.charset)
189+
return HexLiteral(value, charset)
185190
return encoded
186191

187192
def _bytes_to_mysql(self, value):
@@ -537,6 +542,8 @@ def _STRING_to_python(self, value, dsc=None): # pylint: disable=C0103
537542
if dsc[7] & FieldFlag.BINARY:
538543
return value
539544

545+
if self.charset == 'binary':
546+
return value
540547
if isinstance(value, (bytes, bytearray)) and self.use_unicode:
541548
return value.decode(self.charset)
542549

lib/mysql/connector/dbapi.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,22 @@
3636

3737
from . import constants
3838

39-
class _DBAPITypeObject:
39+
class _DBAPITypeObject(object):
4040

4141
def __init__(self, *values):
4242
self.values = values
4343

44-
def __cmp__(self, other):
44+
def __eq__(self, other):
4545
if other in self.values:
46-
return 0
47-
if other < self.values:
48-
return 1
46+
return True
4947
else:
50-
return -1
48+
return False
49+
50+
def __ne__(self, other):
51+
if other in self.values:
52+
return False
53+
else:
54+
return True
5155

5256
Date = datetime.date
5357
Time = datetime.time
@@ -64,8 +68,8 @@ def TimestampFromTicks(ticks):
6468

6569
Binary = bytes
6670

67-
STRING = _DBAPITypeObject(constants.FieldType.get_string_types())
68-
BINARY = _DBAPITypeObject(constants.FieldType.get_binary_types())
69-
NUMBER = _DBAPITypeObject(constants.FieldType.get_number_types())
70-
DATETIME = _DBAPITypeObject(constants.FieldType.get_timestamp_types())
71+
STRING = _DBAPITypeObject(*constants.FieldType.get_string_types())
72+
BINARY = _DBAPITypeObject(*constants.FieldType.get_binary_types())
73+
NUMBER = _DBAPITypeObject(*constants.FieldType.get_number_types())
74+
DATETIME = _DBAPITypeObject(*constants.FieldType.get_timestamp_types())
7175
ROWID = _DBAPITypeObject()

lib/mysql/connector/django/base.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ def _DATETIME_to_python(self, value, dsc=None):
9292
if not value:
9393
return None
9494
dt = MySQLConverter._DATETIME_to_python(self, value)
95+
if dt is None:
96+
return None
9597
if settings.USE_TZ and timezone.is_naive(dt):
9698
dt = dt.replace(tzinfo=timezone.utc)
9799
return dt
@@ -584,7 +586,6 @@ def get_new_connection(self, conn_params):
584586
cnx = mysql.connector.connect(**conn_params)
585587
self.server_version = cnx.get_server_version()
586588
cnx.set_converter_class(DjangoMySQLConverter)
587-
connection_created.send(sender=self.__class__, connection=self)
588589

589590
return cnx
590591

@@ -609,6 +610,7 @@ def create_cursor(self):
609610
def _connect(self):
610611
"""Setup the connection with MySQL"""
611612
self.connection = self.get_new_connection(self.get_connection_params())
613+
connection_created.send(sender=self.__class__, connection=self)
612614
self.init_connection_state()
613615

614616
def _cursor(self):

lib/mysql/connector/errorcode.py

Lines changed: 80 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2525

2626
# This file was auto-generated.
27-
_GENERATED_ON = '2014-05-23'
28-
_MYSQL_VERSION = (5, 7, 4)
27+
_GENERATED_ON = '2014-10-10'
28+
_MYSQL_VERSION = (5, 7, 5)
2929

3030
"""This module contains the MySQL Server and Client error codes"""
3131

@@ -649,7 +649,7 @@
649649
ER_DELAYED_NOT_SUPPORTED = 1616
650650
WARN_NO_MASTER_INFO = 1617
651651
WARN_OPTION_IGNORED = 1618
652-
WARN_PLUGIN_DELETE_BUILTIN = 1619
652+
ER_PLUGIN_DELETE_BUILTIN = 1619
653653
WARN_PLUGIN_BUSY = 1620
654654
ER_VARIABLE_IS_READONLY = 1621
655655
ER_WARN_ENGINE_TRANSACTION_ROLLBACK = 1622
@@ -913,34 +913,82 @@
913913
ER_OLD_TEMPORALS_UPGRADED = 1880
914914
ER_INNODB_FORCED_RECOVERY = 1881
915915
ER_AES_INVALID_IV = 1882
916-
ER_FILE_CORRUPT = 1883
917-
ER_ERROR_ON_MASTER = 1884
918-
ER_INCONSISTENT_ERROR = 1885
919-
ER_STORAGE_ENGINE_NOT_LOADED = 1886
920-
ER_GET_STACKED_DA_WITHOUT_ACTIVE_HANDLER = 1887
921-
ER_WARN_LEGACY_SYNTAX_CONVERTED = 1888
922-
ER_BINLOG_UNSAFE_FULLTEXT_PLUGIN = 1889
923-
ER_CANNOT_DISCARD_TEMPORARY_TABLE = 1890
924-
ER_FK_DEPTH_EXCEEDED = 1891
925-
ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE_V2 = 1892
926-
ER_WARN_TRIGGER_DOESNT_HAVE_CREATED = 1893
927-
ER_REFERENCED_TRG_DOES_NOT_EXIST = 1894
928-
ER_EXPLAIN_NOT_SUPPORTED = 1895
929-
ER_INVALID_FIELD_SIZE = 1896
930-
ER_MISSING_HA_CREATE_OPTION = 1897
931-
ER_ENGINE_OUT_OF_MEMORY = 1898
932-
ER_PASSWORD_EXPIRE_ANONYMOUS_USER = 1899
933-
ER_SLAVE_SQL_THREAD_MUST_STOP = 1900
934-
ER_NO_FT_MATERIALIZED_SUBQUERY = 1901
935-
ER_INNODB_UNDO_LOG_FULL = 1902
936-
ER_INVALID_ARGUMENT_FOR_LOGARITHM = 1903
937-
ER_SLAVE_IO_THREAD_MUST_STOP = 1904
938-
ER_WARN_OPEN_TEMP_TABLES_MUST_BE_ZERO = 1905
939-
ER_WARN_ONLY_MASTER_LOG_FILE_NO_POS = 1906
940-
ER_QUERY_TIMEOUT = 1907
941-
ER_NON_RO_SELECT_DISABLE_TIMER = 1908
942-
ER_DUP_LIST_ENTRY = 1909
943-
ER_SQL_MODE_NO_EFFECT = 1910
916+
ER_PLUGIN_CANNOT_BE_UNINSTALLED = 1883
917+
ER_GTID_UNSAFE_BINLOG_SPLITTABLE_STATEMENT_AND_GTID_GROUP = 1884
918+
ER_FILE_CORRUPT = 1885
919+
ER_ERROR_ON_MASTER = 1886
920+
ER_INCONSISTENT_ERROR = 1887
921+
ER_STORAGE_ENGINE_NOT_LOADED = 1888
922+
ER_GET_STACKED_DA_WITHOUT_ACTIVE_HANDLER = 1889
923+
ER_WARN_LEGACY_SYNTAX_CONVERTED = 1890
924+
ER_BINLOG_UNSAFE_FULLTEXT_PLUGIN = 1891
925+
ER_CANNOT_DISCARD_TEMPORARY_TABLE = 1892
926+
ER_FK_DEPTH_EXCEEDED = 1893
927+
ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE_V2 = 1894
928+
ER_WARN_TRIGGER_DOESNT_HAVE_CREATED = 1895
929+
ER_REFERENCED_TRG_DOES_NOT_EXIST = 1896
930+
ER_EXPLAIN_NOT_SUPPORTED = 1897
931+
ER_INVALID_FIELD_SIZE = 1898
932+
ER_MISSING_HA_CREATE_OPTION = 1899
933+
ER_ENGINE_OUT_OF_MEMORY = 1900
934+
ER_PASSWORD_EXPIRE_ANONYMOUS_USER = 1901
935+
ER_SLAVE_SQL_THREAD_MUST_STOP = 1902
936+
ER_NO_FT_MATERIALIZED_SUBQUERY = 1903
937+
ER_INNODB_UNDO_LOG_FULL = 1904
938+
ER_INVALID_ARGUMENT_FOR_LOGARITHM = 1905
939+
ER_SLAVE_IO_THREAD_MUST_STOP = 1906
940+
ER_WARN_OPEN_TEMP_TABLES_MUST_BE_ZERO = 1907
941+
ER_WARN_ONLY_MASTER_LOG_FILE_NO_POS = 1908
942+
ER_QUERY_TIMEOUT = 1909
943+
ER_NON_RO_SELECT_DISABLE_TIMER = 1910
944+
ER_DUP_LIST_ENTRY = 1911
945+
ER_SQL_MODE_NO_EFFECT = 1912
946+
ER_AGGREGATE_ORDER_FOR_UNION = 1913
947+
ER_AGGREGATE_ORDER_NON_AGG_QUERY = 1914
948+
ER_SLAVE_WORKER_STOPPED_PREVIOUS_THD_ERROR = 1915
949+
ER_DONT_SUPPORT_SLAVE_PRESERVE_COMMIT_ORDER = 1916
950+
ER_SERVER_OFFLINE_MODE = 1917
951+
ER_GIS_DIFFERENT_SRIDS = 1918
952+
ER_GIS_UNSUPPORTED_ARGUMENT = 1919
953+
ER_GIS_UNKNOWN_ERROR = 1920
954+
ER_GIS_UNKNOWN_EXCEPTION = 1921
955+
ER_GIS_INVALID_DATA = 1922
956+
ER_BOOST_GEOMETRY_EMPTY_INPUT_EXCEPTION = 1923
957+
ER_BOOST_GEOMETRY_CENTROID_EXCEPTION = 1924
958+
ER_BOOST_GEOMETRY_OVERLAY_INVALID_INPUT_EXCEPTION = 1925
959+
ER_BOOST_GEOMETRY_TURN_INFO_EXCEPTION = 1926
960+
ER_BOOST_GEOMETRY_SELF_INTERSECTION_POINT_EXCEPTION = 1927
961+
ER_BOOST_GEOMETRY_UNKNOWN_EXCEPTION = 1928
962+
ER_STD_BAD_ALLOC_ERROR = 1929
963+
ER_STD_DOMAIN_ERROR = 1930
964+
ER_STD_LENGTH_ERROR = 1931
965+
ER_STD_INVALID_ARGUMENT = 1932
966+
ER_STD_OUT_OF_RANGE_ERROR = 1933
967+
ER_STD_OVERFLOW_ERROR = 1934
968+
ER_STD_RANGE_ERROR = 1935
969+
ER_STD_UNDERFLOW_ERROR = 1936
970+
ER_STD_LOGIC_ERROR = 1937
971+
ER_STD_RUNTIME_ERROR = 1938
972+
ER_STD_UNKNOWN_EXCEPTION = 1939
973+
ER_GIS_DATA_WRONG_ENDIANESS = 1940
974+
ER_CHANGE_MASTER_PASSWORD_LENGTH = 1941
975+
ER_USER_LOCK_WRONG_NAME = 1942
976+
ER_USER_LOCK_DEADLOCK = 1943
977+
ER_REPLACE_INACCESSIBLE_ROWS = 1944
978+
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_GIS = 1945
979+
ER_ILLEGAL_USER_VAR = 1946
980+
ER_GTID_MODE_OFF = 1947
981+
ER_UNSUPPORTED_BY_REPLICATION_THREAD = 1948
982+
ER_INCORRECT_TYPE = 1949
983+
ER_FIELD_IN_ORDER_NOT_SELECT = 1950
984+
ER_AGGREGATE_IN_ORDER_NOT_SELECT = 1951
985+
ER_INVALID_RPL_WILD_TABLE_FILTER_PATTERN = 1952
986+
ER_NET_OK_PACKET_TOO_LARGE = 1953
987+
ER_INVALID_JSON_DATA = 1954
988+
ER_INVALID_GEOJSON_MISSING_MEMBER = 1955
989+
ER_INVALID_GEOJSON_WRONG_TYPE = 1956
990+
ER_INVALID_GEOJSON_UNSPECIFIED = 1957
991+
ER_DIMENSION_UNSUPPORTED = 1958
944992
CR_UNKNOWN_ERROR = 2000
945993
CR_SOCKET_CREATE_ERROR = 2001
946994
CR_CONNECTION_ERROR = 2002
@@ -990,7 +1038,7 @@
9901038
CR_SHARED_MEMORY_CONNECT_SET_ERROR = 2046
9911039
CR_CONN_UNKNOW_PROTOCOL = 2047
9921040
CR_INVALID_CONN_HANDLE = 2048
993-
CR_SECURE_AUTH = 2049
1041+
CR_UNUSED_1 = 2049
9941042
CR_FETCH_CANCELED = 2050
9951043
CR_NO_DATA = 2051
9961044
CR_NO_STMT_METADATA = 2052

lib/mysql/connector/fabric/caching.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"""Implementing caching mechanisms for MySQL Fabric"""
2525

2626

27+
import bisect
2728
from datetime import datetime, timedelta
2829
from hashlib import sha1
2930
import logging
@@ -35,6 +36,26 @@
3536
_CACHE_TTL = 1 * 60 # 1 minute
3637

3738

39+
def insort_right_rev(alist, new_element, low=0, high=None):
40+
"""Similar to bisect.insort_right but for reverse sorted lists
41+
42+
This code is similar to the Python code found in Lib/bisect.py.
43+
We simply change the comparison from 'less than' to 'greater than'.
44+
"""
45+
46+
if low < 0:
47+
raise ValueError('low must be non-negative')
48+
if high is None:
49+
high = len(alist)
50+
while low < high:
51+
middle = (low + high) // 2
52+
if new_element > alist[middle]:
53+
high = middle
54+
else:
55+
low = middle + 1
56+
alist.insert(low, new_element)
57+
58+
3859
class CacheEntry(object):
3960

4061
"""Base class for MySQL Fabric cache entries"""
@@ -83,6 +104,8 @@ def __init__(self, shard, version=None, fabric_uuid=None):
83104
fabric_uuid=fabric_uuid)
84105
self.partitioning = {}
85106
self._shard = shard
107+
self.keys = []
108+
self.keys_reversed = []
86109

87110
if shard.key and shard.group:
88111
self.add_partition(shard.key, shard.group)
@@ -115,6 +138,8 @@ def add_partition(self, key, group):
115138
'group': group,
116139
}
117140
self.reset_ttl()
141+
bisect.insort_right(self.keys, key)
142+
insort_right_rev(self.keys_reversed, key)
118143

119144
@classmethod
120145
def hash_index(cls, part1, part2=None):

0 commit comments

Comments
 (0)