From f5e57f7c311288d892894edcc44d901b5bfbb3d1 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sun, 11 Aug 2019 17:42:59 -0400 Subject: Emit SET NAMES for all MySQL connections w charset The MySQL dialects will emit "SET NAMES" at the start of a connection when charset is given to the MySQL driver, to appease an apparent behavior observed in MySQL 8.0 that raises a collation error when a UNION includes string columns unioned against columns of the form CAST(NULL AS CHAR(..)), which is what SQLAlchemy's polymorphic_union function does. The issue seems to have affected PyMySQL for at least a year, however has recently appeared as of mysqlclient 1.4.4 based on changes in how this DBAPI creates a connection. As the presence of this directive impacts three separate MySQL charset settings which each have intricate effects based on their presense, SQLAlchemy will now emit the directive on new connections to ensure correct behavior. Fixes: #4804 Change-Id: If9d7ee00d0ccaf773972b564fe455e8e9edf6627 --- lib/sqlalchemy/dialects/mysql/mysqldb.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'lib/sqlalchemy/dialects/mysql/mysqldb.py') diff --git a/lib/sqlalchemy/dialects/mysql/mysqldb.py b/lib/sqlalchemy/dialects/mysql/mysqldb.py index 744909170..1d4dba3c4 100644 --- a/lib/sqlalchemy/dialects/mysql/mysqldb.py +++ b/lib/sqlalchemy/dialects/mysql/mysqldb.py @@ -117,6 +117,22 @@ class MySQLDialect_mysqldb(MySQLDialect): def dbapi(cls): return __import__("MySQLdb") + def on_connect(self): + super_ = super(MySQLDialect_mysqldb, self).on_connect() + + def on_connect(conn): + if super_ is not None: + super_(conn) + + charset_name = conn.character_set_name() + + if charset_name is not None: + cursor = conn.cursor() + cursor.execute("SET NAMES %s" % charset_name) + cursor.close() + + return on_connect + def do_ping(self, dbapi_connection): try: dbapi_connection.ping(False) -- cgit v1.2.1