summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Caselli <cfederico87@gmail.com>2022-01-04 20:30:16 +0000
committerGerrit Code Review <gerrit@ci3.zzzcomputing.com>2022-01-04 20:30:16 +0000
commit4dfc24cda51b45ef10c68fb603b325c0b45099d2 (patch)
treeb39ad78050a20eda5ac51ab34f6b0f2b5c45ff27
parent5a76f52256ca856f245f584869d6b9a4b10d4460 (diff)
parent5e06f0f579df45116696fed78d65abcccc1dc3e3 (diff)
downloadsqlalchemy-4dfc24cda51b45ef10c68fb603b325c0b45099d2.tar.gz
Merge "Imrpove MySQL/MariaDB dialect initialization." into main
-rw-r--r--doc/build/changelog/unreleased_14/7518.rst8
-rw-r--r--lib/sqlalchemy/dialects/mysql/base.py19
-rw-r--r--lib/sqlalchemy/dialects/mysql/pyodbc.py29
-rw-r--r--test/dialect/mysql/test_dialect.py2
4 files changed, 29 insertions, 29 deletions
diff --git a/doc/build/changelog/unreleased_14/7518.rst b/doc/build/changelog/unreleased_14/7518.rst
new file mode 100644
index 000000000..6264297cb
--- /dev/null
+++ b/doc/build/changelog/unreleased_14/7518.rst
@@ -0,0 +1,8 @@
+.. change::
+ :tags: change, mysql
+ :tickets: 7518
+
+ Replace ``SHOW VARIABLES LIKE`` statement with equivalent
+ ``SELECT @@variable`` in MySQL and MariaDB dialect initialization.
+ This should avoid mutex contention caused by ``SHOW VARIABLES``,
+ improving initialization performance.
diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py
index 5be057495..f20b9b693 100644
--- a/lib/sqlalchemy/dialects/mysql/base.py
+++ b/lib/sqlalchemy/dialects/mysql/base.py
@@ -3079,24 +3079,21 @@ class MySQLDialect(default.DefaultDialect):
# https://dev.mysql.com/doc/refman/en/identifier-case-sensitivity.html
charset = self._connection_charset
- show_var = connection.execute(
- sql.text("SHOW VARIABLES LIKE 'lower_case_table_names'")
- )
- row = self._compat_first(
- show_var,
- charset=charset,
+ show_var = connection.exec_driver_sql(
+ "SELECT @@lower_case_table_names"
)
+ row = self._compat_first(show_var, charset=charset)
if not row:
cs = 0
else:
# 4.0.15 returns OFF or ON according to [ticket:489]
# 3.23 doesn't, 4.0.27 doesn't..
- if row[1] == "OFF":
+ if row[0] == "OFF":
cs = 0
- elif row[1] == "ON":
+ elif row[0] == "ON":
cs = 1
else:
- cs = int(row[1])
+ cs = int(row[0])
self._casing = cs
return cs
@@ -3115,7 +3112,7 @@ class MySQLDialect(default.DefaultDialect):
def _detect_sql_mode(self, connection):
row = self._compat_first(
- connection.exec_driver_sql("SHOW VARIABLES LIKE 'sql_mode'"),
+ connection.exec_driver_sql("SELECT @@sql_mode"),
charset=self._connection_charset,
)
@@ -3126,7 +3123,7 @@ class MySQLDialect(default.DefaultDialect):
)
self._sql_mode = ""
else:
- self._sql_mode = row[1] or ""
+ self._sql_mode = row[0] or ""
def _detect_ansiquotes(self, connection):
"""Detect and adjust for the ANSI_QUOTES sql mode."""
diff --git a/lib/sqlalchemy/dialects/mysql/pyodbc.py b/lib/sqlalchemy/dialects/mysql/pyodbc.py
index 69cc6487d..9cae7b714 100644
--- a/lib/sqlalchemy/dialects/mysql/pyodbc.py
+++ b/lib/sqlalchemy/dialects/mysql/pyodbc.py
@@ -43,11 +43,11 @@ Pass through exact pyodbc connection string::
""" # noqa
import re
-import sys
from .base import MySQLDialect
from .base import MySQLExecutionContext
from .types import TIME
+from ... import exc
from ... import util
from ...connectors.pyodbc import PyODBCConnector
from ...sql.sqltypes import Time
@@ -88,13 +88,14 @@ class MySQLDialect_pyodbc(PyODBCConnector, MySQLDialect):
#
# If it's decided that issuing that sort of SQL leaves you SOL, then
# this can prefer the driver value.
- rs = connection.exec_driver_sql(
- "SHOW VARIABLES LIKE 'character_set%%'"
- )
- opts = {row[0]: row[1] for row in self._compat_fetchall(rs)}
- for key in ("character_set_connection", "character_set"):
- if opts.get(key, None):
- return opts[key]
+ try:
+ value = connection.exec_driver_sql(
+ "select @@character_set_client"
+ ).scalar()
+ if value:
+ return value
+ except exc.DBAPIError:
+ pass
util.warn(
"Could not detect the connection character set. "
@@ -121,15 +122,9 @@ class MySQLDialect_pyodbc(PyODBCConnector, MySQLDialect):
# https://github.com/mkleehammer/pyodbc/wiki/Unicode
pyodbc_SQL_CHAR = 1 # pyodbc.SQL_CHAR
pyodbc_SQL_WCHAR = -8 # pyodbc.SQL_WCHAR
- if sys.version_info.major > 2:
- conn.setdecoding(pyodbc_SQL_CHAR, encoding="utf-8")
- conn.setdecoding(pyodbc_SQL_WCHAR, encoding="utf-8")
- conn.setencoding(encoding="utf-8")
- else:
- conn.setdecoding(pyodbc_SQL_CHAR, encoding="utf-8")
- conn.setdecoding(pyodbc_SQL_WCHAR, encoding="utf-8")
- conn.setencoding(str, encoding="utf-8")
- conn.setencoding(unicode, encoding="utf-8") # noqa: F821
+ conn.setdecoding(pyodbc_SQL_CHAR, encoding="utf-8")
+ conn.setdecoding(pyodbc_SQL_WCHAR, encoding="utf-8")
+ conn.setencoding(encoding="utf-8")
return on_connect
diff --git a/test/dialect/mysql/test_dialect.py b/test/dialect/mysql/test_dialect.py
index 9a0f2bc0d..a96ea8cb4 100644
--- a/test/dialect/mysql/test_dialect.py
+++ b/test/dialect/mysql/test_dialect.py
@@ -59,7 +59,7 @@ class BackendDialectTest(
engine = engines.testing_engine()
def my_execute(self, statement, *args, **kw):
- if statement.startswith("SHOW VARIABLES"):
+ if statement.startswith("SELECT @@"):
statement = "SELECT 1 FROM DUAL WHERE 1=0"
return real_exec(self, statement, *args, **kw)