Skip to content

Commit 60a32f4

Browse files
author
Geert Vanderkelen
committed
Merge branch 'WL7954' into develop
2 parents 4294703 + 868572a commit 60a32f4

File tree

4 files changed

+97
-22
lines changed

4 files changed

+97
-22
lines changed

lib/mysql/connector/catch23.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@
3535

3636
if PY2:
3737
NUMERIC_TYPES = (int, float, Decimal, HexLiteral, long)
38+
UNICODE_TYPES = (unicode,) # This should not contain str
3839
else:
3940
NUMERIC_TYPES = (int, float, Decimal, HexLiteral)
41+
UNICODE_TYPES = (str,)
4042

4143
def init_bytearray(payload=b'', encoding='utf-8'):
4244
"""Initializes a bytearray from the payload"""
@@ -65,6 +67,13 @@ def isstr(obj):
6567
else:
6668
return isinstance(obj, str)
6769

70+
def isunicode(obj):
71+
"""Returns whether a variable is a of unicode type"""
72+
if PY2:
73+
return isinstance(obj, unicode)
74+
else:
75+
return isinstance(obj, str)
76+
6877

6978
if PY2:
7079
def struct_unpack(fmt, buf):

lib/mysql/connector/fabric/caching.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ def add_partition(self, key, group):
105105
"RANGE_DATETIME key could not be parsed, was: {0}".format(
106106
key
107107
))
108+
elif self.shard_type == 'RANGE_STRING':
109+
pass
108110
else:
109111
raise ValueError("Unsupported sharding type {0}".format(
110112
self.shard_type

lib/mysql/connector/fabric/connection.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
from .caching import FabricCache
7777
from .balancing import WeightedRoundRobin
7878
from .. import version
79-
from ..catch23 import PY2
79+
from ..catch23 import PY2, isunicode, UNICODE_TYPES
8080

8181
RESET_CACHE_ON_ERROR = (
8282
errorcode.CR_SERVER_LOST,
@@ -122,7 +122,8 @@
122122
_CNX_PROPERTIES = {
123123
# name: ((valid_types), description, default)
124124
'group': ((str,), "Name of group of servers", None),
125-
'key': ((int, str, datetime.datetime, datetime.date),
125+
'key': (tuple([int, str, datetime.datetime,
126+
datetime.date] + list(UNICODE_TYPES)),
126127
"Sharding key", None),
127128
'tables': ((tuple, list), "List of tables in query", None),
128129
'mode': ((int,), "Read-Only, Write-Only or Read-Write", MODE_READWRITE),
@@ -766,6 +767,16 @@ def get_shard_server(self, tables, key, scope=SCOPE_LOCAL, mode=None):
766767
index = partkey
767768
break
768769
partition = entry.partitioning[index]
770+
elif entry.shard_type == 'RANGE_STRING':
771+
if not isunicode(key):
772+
raise ValueError("Key must be a unicode value")
773+
partition_keys = sorted(entry.partitioning.keys(), reverse=True)
774+
for partkey in partition_keys:
775+
size = len(partkey)
776+
if key[0:size] >= partkey[0:size]:
777+
index = partkey
778+
break
779+
partition = entry.partitioning[index]
769780
elif entry.shard_type == 'HASH':
770781
md5key = md5(str(key))
771782
partition_keys = sorted(

tests/test_fabric.py

Lines changed: 73 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import mysql.connector
4141
from mysql.connector import fabric, errorcode
4242
from mysql.connector.fabric import connection, balancing
43+
from mysql.connector.catch23 import UNICODE_TYPES, PY2
4344

4445
ERR_NO_FABRIC_CONFIG = "Fabric configuration not available"
4546

@@ -148,7 +149,8 @@ def test_cnx_properties(self):
148149
cnxprops = {
149150
# name: (valid_types, description, default)
150151
'group': ((str,), "Name of group of servers", None),
151-
'key': ((int, str, datetime.datetime, datetime.date),
152+
'key': (tuple([int, str, datetime.datetime,
153+
datetime.date] + list(UNICODE_TYPES)),
152154
"Sharding key", None),
153155
'tables': ((tuple, list), "List of tables in query", None),
154156
'mode': ((int,), "Read-Only, Write-Only or Read-Write",
@@ -365,10 +367,25 @@ def test___eq__(self):
365367
self.assertFalse(balancer1 == balancer3)
366368

367369
@unittest.skipIf(not tests.FABRIC_CONFIG, ERR_NO_FABRIC_CONFIG)
368-
class FabricSharding(tests.MySQLConnectorTests):
370+
class FabricShardingTests(tests.MySQLConnectorTests):
369371

370372
"""Test Fabric's sharding"""
371373

374+
emp_data = {
375+
1985: [
376+
(10001, datetime.date(1953, 9, 2), u'Georgi', u'Facello', u'M',
377+
datetime.date(1986, 6, 26)),
378+
(10002, datetime.date(1964, 6, 2), u'Bezalel', u'Simmel', u'F',
379+
datetime.date(1985, 11, 21)),
380+
],
381+
2000: [
382+
(47291, datetime.date(1960, 9, 9), u'Ulf', u'Flexer', u'M',
383+
datetime.date(2000, 1, 12)),
384+
(60134, datetime.date(1964, 4, 21), u'Seshu', u'Rathonyi', u'F',
385+
datetime.date(2000, 1, 2)),
386+
]
387+
}
388+
372389
def setUp(self):
373390
self.cnx = mysql.connector.connect(
374391
fabric=tests.FABRIC_CONFIG, user='root', database='employees'
@@ -421,27 +438,11 @@ def test_range_datetime(self):
421438
gtid_executed = self._truncate(cur, tbl_name)
422439
self.cnx.commit()
423440

424-
employee_data = {
425-
1985: [
426-
(10001, datetime.date(1953, 9, 2), u'Georgi', u'Facello', u'M',
427-
datetime.date(1986, 6, 26)),
428-
(10002, datetime.date(1964, 6, 2), u'Bezalel', u'Simmel', u'F',
429-
datetime.date(1985, 11, 21)),
430-
],
431-
2000: [
432-
(47291, datetime.date(1960, 9, 9), u'Ulf', u'Flexer', u'M',
433-
datetime.date(2000, 1, 12)),
434-
(60134, datetime.date(1964, 4, 21), u'Seshu', u'Rathonyi', u'F',
435-
datetime.date(2000, 1, 2)),
436-
]
437-
}
438-
439441
insert = ("INSERT INTO {0} "
440442
"VALUES (%s, %s, %s, %s, %s, %s)").format(tbl_name)
441443

442444
self._populate(self.cnx, gtid_executed, tbl_name, insert,
443-
employee_data[1985] + employee_data[2000],
444-
5)
445+
self.emp_data[1985] + self.emp_data[2000], 5)
445446

446447
time.sleep(2)
447448

@@ -452,8 +453,60 @@ def test_range_datetime(self):
452453
cur = self.cnx.cursor()
453454
cur.execute("SELECT * FROM {0}".format(tbl_name))
454455
rows = cur.fetchall()
455-
self.assertEqual(rows, employee_data[hire_date.year])
456+
self.assertEqual(rows, self.emp_data[hire_date.year])
456457

457458
self.cnx.set_property(tables=tables,
458459
key='2014-01-02', mode=fabric.MODE_READONLY)
459460
self.assertRaises(ValueError, self.cnx.cursor)
461+
462+
def test_range_string(self):
463+
self.assertTrue(self._check_table(
464+
"employees.employees_range_string", 'RANGE_STRING'))
465+
tbl_name = "employees_range_string"
466+
467+
tables = ["employees.{0}".format(tbl_name)]
468+
469+
self.cnx.set_property(tables=tables,
470+
scope=fabric.SCOPE_GLOBAL,
471+
mode=fabric.MODE_READWRITE)
472+
cur = self.cnx.cursor()
473+
gtid_executed = self._truncate(cur, tbl_name)
474+
self.cnx.commit()
475+
476+
insert = ("INSERT INTO {0} "
477+
"VALUES (%s, %s, %s, %s, %s, %s)").format(tbl_name)
478+
479+
self._populate(self.cnx, gtid_executed, tbl_name, insert,
480+
self.emp_data[1985] + self.emp_data[2000], 3)
481+
482+
time.sleep(2)
483+
484+
emp_exp_range_string = {
485+
'A': [self.emp_data[1985][0],
486+
self.emp_data[2000][0]],
487+
'M': [self.emp_data[1985][1],
488+
self.emp_data[2000][1]],
489+
}
490+
491+
str_keys = [u'A', u'M']
492+
for str_key in str_keys:
493+
self.cnx.set_property(tables=tables,
494+
key=str_key, mode=fabric.MODE_READONLY)
495+
cur = self.cnx.cursor()
496+
cur.execute("SELECT * FROM {0}".format(tbl_name))
497+
rows = cur.fetchall()
498+
self.assertEqual(rows, emp_exp_range_string[str_key])
499+
500+
self.cnx.set_property(tables=tables,
501+
key=b'not unicode str', mode=fabric.MODE_READONLY)
502+
self.assertRaises(ValueError, self.cnx.cursor)
503+
504+
self.cnx.set_property(tables=tables,
505+
key=12345, mode=fabric.MODE_READONLY)
506+
self.assertRaises(ValueError, self.cnx.cursor)
507+
508+
if PY2:
509+
self.cnx.set_property(tables=tables,
510+
key='not unicode str',
511+
mode=fabric.MODE_READONLY)
512+
self.assertRaises(ValueError, self.cnx.cursor)

0 commit comments

Comments
 (0)