summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2018-06-27 16:08:23 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2018-06-27 19:15:19 -0400
commit83750628d180b9b9e5a6ae9a2ecb3a001553cb81 (patch)
tree1a1d10ec932d53d7119bf7c788388d2d9f414562
parenta0d1030096af8f6cdd2e2fb7668224ade2d87c8f (diff)
downloadsqlalchemy-83750628d180b9b9e5a6ae9a2ecb3a001553cb81.tar.gz
Try to get mysqlconnector somewhat working
Add CI support for MySQL connector and try to fix some of the more obvious issues. CI tests will run against MySQL 5.7 only for starters as there appear to be issues with MySQL 8.0 Change-Id: Id8971143a8385a5c84f0646c21c4c21e793ce3a2
-rw-r--r--doc/build/changelog/unreleased_12/mysqlconnector_percents.rst12
-rw-r--r--lib/sqlalchemy/dialects/mysql/mysqlconnector.py58
-rw-r--r--test/dialect/mysql/test_for_update.py1
-rw-r--r--test/requirements.py7
-rw-r--r--tox.ini1
5 files changed, 75 insertions, 4 deletions
diff --git a/doc/build/changelog/unreleased_12/mysqlconnector_percents.rst b/doc/build/changelog/unreleased_12/mysqlconnector_percents.rst
new file mode 100644
index 000000000..c12dd5f43
--- /dev/null
+++ b/doc/build/changelog/unreleased_12/mysqlconnector_percents.rst
@@ -0,0 +1,12 @@
+.. change::
+ :tags: bug, mysql
+
+ Fixed percent-sign doubling in mysql-connector-python dialect, which does
+ not require de-doubling of percent signs. Additionally, the mysql-
+ connector-python driver is inconsistent in how it passes the column names
+ in cursor.description, so a workaround decoder has been added to
+ conditionally decode these randomly-sometimes-bytes values to unicode only
+ if needed. Also improved test support for mysql-connector-python, however
+ it should be noted that this driver still has issues with unicode that
+ continue to be unresolved as of yet.
+
diff --git a/lib/sqlalchemy/dialects/mysql/mysqlconnector.py b/lib/sqlalchemy/dialects/mysql/mysqlconnector.py
index 117115888..f7b3bd670 100644
--- a/lib/sqlalchemy/dialects/mysql/mysqlconnector.py
+++ b/lib/sqlalchemy/dialects/mysql/mysqlconnector.py
@@ -14,11 +14,33 @@
:url: http://dev.mysql.com/downloads/connector/python/
-Unicode
--------
+Current Issues
+--------------
-Please see :ref:`mysql_unicode` for current recommendations on unicode
-handling.
+The mysqlconnector driver has many issues that have gone unresolved
+for many years and it recommended that mysqlclient or pymysql be used
+if possible; as of June 27, 2018:
+
+* the values in cursor.description are randomly sent as either bytes
+ or text with no discernible pattern, so the dialect must test these
+ individually and attempt to decode
+
+* Under Python 2, the driver does not support SQL statements that contain
+ non-ascii characters within the SQL text, making it impossible to support
+ schema objects with non-ascii names; an ascii encoding error is raised.
+
+* additional random bytes-returned issues occur when running under MySQL 8.0
+ only
+
+* The driver does not accept the "utf8mb4" or "utf8mb3" charset parameters,
+ only "utf8", even though MySQL itself has deprecated this symbol
+
+* The driver produces deadlocks when trying to make use of SELECT..FOR UPDATE,
+ the reason is unknown.
+
+This list should be updated as these issues are resolved either in the
+upstream mysql-connector-python driver or if appropriate usage patterns
+are contributed to SQLAlchemy.
"""
@@ -28,6 +50,7 @@ from .base import (MySQLDialect, MySQLExecutionContext,
from ... import util
import re
+from ... import processors
class MySQLExecutionContext_mysqlconnector(MySQLExecutionContext):
@@ -59,6 +82,13 @@ class MySQLCompiler_mysqlconnector(MySQLCompiler):
class MySQLIdentifierPreparer_mysqlconnector(MySQLIdentifierPreparer):
+ @property
+ def _double_percents(self):
+ return self.dialect._mysqlconnector_double_percents
+
+ @_double_percents.setter
+ def _double_percents(self, value):
+ pass
def _escape_identifier(self, value):
value = value.replace(self.escape_quote, self.escape_to_quote)
@@ -98,6 +128,26 @@ class MySQLDialect_mysqlconnector(MySQLDialect):
}
)
+ def __init__(self, *arg, **kw):
+ super(MySQLDialect_mysqlconnector, self).__init__(*arg, **kw)
+
+ # hack description encoding since mysqlconnector randomly
+ # returns bytes or not
+ self._description_decoder = \
+ processors.to_conditional_unicode_processor_factory(
+ self.description_encoding
+ )
+
+ def _check_unicode_description(self, connection):
+ # hack description encoding since mysqlconnector randomly
+ # returns bytes or not
+ return False
+
+ @property
+ def description_encoding(self):
+ # total guess
+ return "latin-1"
+
@util.memoized_property
def supports_unicode_statements(self):
return util.py3k or self._mysqlconnector_version_info > (2, 0)
diff --git a/test/dialect/mysql/test_for_update.py b/test/dialect/mysql/test_for_update.py
index af467f920..a8cbcfb87 100644
--- a/test/dialect/mysql/test_for_update.py
+++ b/test/dialect/mysql/test_for_update.py
@@ -16,6 +16,7 @@ from sqlalchemy import testing
class MySQLForUpdateLockingTest(fixtures.DeclarativeMappedTest):
__backend__ = True
__only_on__ = 'mysql'
+ __requires__ = 'mysql_for_update',
@classmethod
def setup_classes(cls):
diff --git a/test/requirements.py b/test/requirements.py
index 3cc80318c..57324a3f4 100644
--- a/test/requirements.py
+++ b/test/requirements.py
@@ -1084,6 +1084,13 @@ class DefaultRequirements(SuiteRequirements):
"non-standard SELECT scalar syntax")
@property
+ def mysql_for_update(self):
+ return skip_if(
+ "mysql+mysqlconnector",
+ "lock-sensitive operations crash on mysqlconnector"
+ )
+
+ @property
def mysql_fsp(self):
return only_if('mysql >= 5.6.4')
diff --git a/tox.ini b/tox.ini
index a84a7cf16..4e29c5876 100644
--- a/tox.ini
+++ b/tox.ini
@@ -21,6 +21,7 @@ deps=pytest
postgresql: psycopg2>=2.7
mysql: mysqlclient
mysql: pymysql
+ mysql: mysql-connector-python
# waiting for https://github.com/oracle/python-cx_Oracle/issues/75
oracle: cx_oracle>=6.0.2,!=6.3
oracle5: cx_oracle==5.2.1