summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/build/changelog/unreleased_13/4804.rst15
-rw-r--r--lib/sqlalchemy/dialects/mysql/mysqldb.py16
-rw-r--r--lib/sqlalchemy/testing/suite/test_types.py2
-rw-r--r--test/profiles.txt16
4 files changed, 38 insertions, 11 deletions
diff --git a/doc/build/changelog/unreleased_13/4804.rst b/doc/build/changelog/unreleased_13/4804.rst
new file mode 100644
index 000000000..58f521e5b
--- /dev/null
+++ b/doc/build/changelog/unreleased_13/4804.rst
@@ -0,0 +1,15 @@
+.. change::
+ :tags: bug, mysql
+ :tickets: 4804
+
+ 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.
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)
diff --git a/lib/sqlalchemy/testing/suite/test_types.py b/lib/sqlalchemy/testing/suite/test_types.py
index 3320dd93c..82a842102 100644
--- a/lib/sqlalchemy/testing/suite/test_types.py
+++ b/lib/sqlalchemy/testing/suite/test_types.py
@@ -733,7 +733,7 @@ class JSONTest(_LiteralRoundTripFixture, fixtures.TablesTest):
def test_round_trip_custom_json(self):
data_table = self.tables.data_table
- data_element = self.data1
+ data_element = {"key1": "data1"}
js = mock.Mock(side_effect=json.dumps)
jd = mock.Mock(side_effect=json.loads)
diff --git a/test/profiles.txt b/test/profiles.txt
index 469dac01c..10288669b 100644
--- a/test/profiles.txt
+++ b/test/profiles.txt
@@ -1,15 +1,15 @@
# /home/classic/dev/sqlalchemy/test/profiles.txt
# This file is written out on a per-environment basis.
-# For each test in aaa_profiling, the corresponding function and
+# For each test in aaa_profiling, the corresponding function and
# environment is located within this file. If it doesn't exist,
# the test is skipped.
-# If a callcount does exist, it is compared to what we received.
+# If a callcount does exist, it is compared to what we received.
# assertions are raised if the counts do not match.
-#
-# To add a new callcount test, apply the function_call_count
-# decorator and re-run the tests using the --write-profiles
+#
+# To add a new callcount test, apply the function_call_count
+# decorator and re-run the tests using the --write-profiles
# option - this file will be rewritten including the new count.
-#
+#
# TEST: test.aaa_profiling.test_compiler.CompileTest.test_insert
@@ -487,8 +487,6 @@ test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 3.
test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_mssql_pyodbc_dbapiunicode_cextensions 1045
test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_mssql_pyodbc_dbapiunicode_nocextensions 1062
-test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_mysql_mysqldb_dbapiunicode_cextensions 1196
-test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_mysql_mysqldb_dbapiunicode_nocextensions 1213
test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_oracle_cx_oracle_dbapiunicode_cextensions 1111
test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 1128
test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_postgresql_psycopg2_dbapiunicode_cextensions 1143
@@ -508,8 +506,6 @@ test.aaa_profiling.test_orm.MergeTest.test_merge_load 3.7_sqlite_pysqlite_dbapiu
test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.7_mssql_pyodbc_dbapiunicode_cextensions 93,19
test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.7_mssql_pyodbc_dbapiunicode_nocextensions 93,19
-test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.7_mysql_mysqldb_dbapiunicode_cextensions 93,19
-test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.7_mysql_mysqldb_dbapiunicode_nocextensions 93,19
test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.7_oracle_cx_oracle_dbapiunicode_cextensions 93,19
test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 93,19
test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.7_postgresql_psycopg2_dbapiunicode_cextensions 100,19