summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/databases/mysql.py
diff options
context:
space:
mode:
authorJason Kirtland <jek@discorporate.us>2008-02-05 17:26:35 +0000
committerJason Kirtland <jek@discorporate.us>2008-02-05 17:26:35 +0000
commit96549e6b8fd353a82a77938a754bd168a924385b (patch)
tree829b401c09a47ee52b22a094d171cfdb406aae5c /lib/sqlalchemy/databases/mysql.py
parentdc98505f2f182b099dddcba45c518584e131a039 (diff)
downloadsqlalchemy-96549e6b8fd353a82a77938a754bd168a924385b.tar.gz
- Autodetect mysql's ANSI_QUOTES mode, sometimes. [ticket:845]
The dialect needs a hook run on first pool connect to detect this most of the time, and a refactor with Dialect-per-Connection to get it right all of the time. (It's a connection-session scoped setting with dialect-modifying behavior)
Diffstat (limited to 'lib/sqlalchemy/databases/mysql.py')
-rw-r--r--lib/sqlalchemy/databases/mysql.py75
1 files changed, 67 insertions, 8 deletions
diff --git a/lib/sqlalchemy/databases/mysql.py b/lib/sqlalchemy/databases/mysql.py
index e01cec2ab..314cb8dac 100644
--- a/lib/sqlalchemy/databases/mysql.py
+++ b/lib/sqlalchemy/databases/mysql.py
@@ -95,6 +95,16 @@ by supplying ``--sql-mode`` to ``mysqld``. You can also use a ``Pool`` hook
to issue a ``SET SESSION sql_mode='...'`` on connect to configure each
connection.
+If you do not specify 'use_ansiquotes', the regular MySQL quoting style is
+used by default. Table reflection operations will query the server
+
+If you do issue a 'SET sql_mode' through SQLAlchemy, the dialect must be
+updated if the quoting style is changed. Again, this change will affect all
+connections::
+
+ connection.execute('SET sql_mode="ansi"')
+ connection.dialect.use_ansiquotes = True
+
For normal SQLAlchemy usage, loading this module is unnescesary. It will be
loaded on-demand when a MySQL connection is needed. The generic column types
like ``String`` and ``Integer`` will automatically be adapted to the optimal
@@ -1401,13 +1411,9 @@ class MySQLDialect(default.DefaultDialect):
max_identifier_length = 255
supports_sane_rowcount = True
- def __init__(self, use_ansiquotes=False, **kwargs):
+ def __init__(self, use_ansiquotes=None, **kwargs):
self.use_ansiquotes = use_ansiquotes
kwargs.setdefault('default_paramstyle', 'format')
- if self.use_ansiquotes:
- self.preparer = MySQLANSIIdentifierPreparer
- else:
- self.preparer = MySQLIdentifierPreparer
default.DefaultDialect.__init__(self, **kwargs)
def dbapi(cls):
@@ -1546,6 +1552,7 @@ class MySQLDialect(default.DefaultDialect):
"""Return a Unicode SHOW TABLES from a given schema."""
charset = self._detect_charset(connection)
+ self._autoset_identifier_style(connection)
rp = connection.execute("SHOW TABLES FROM %s" %
self.identifier_preparer.quote_identifier(schema))
return [row[0] for row in _compat_fetchall(rp, charset=charset)]
@@ -1558,7 +1565,10 @@ class MySQLDialect(default.DefaultDialect):
# based on platform. DESCRIBE is slower.
# [ticket:726]
- # full_name = self.identifier_preparer.format_table(table, use_schema=True)
+ # full_name = self.identifier_preparer.format_table(table,
+ # use_schema=True)
+
+ self._autoset_identifier_style(connection)
full_name = '.'.join(self.identifier_preparer._quote_free_identifiers(
schema, table_name))
@@ -1627,12 +1637,18 @@ class MySQLDialect(default.DefaultDialect):
"""Load column definitions from the server."""
charset = self._detect_charset(connection)
+ self._autoset_identifier_style(connection)
try:
reflector = self.reflector
except AttributeError:
- self.reflector = reflector = \
- MySQLSchemaReflector(self.identifier_preparer)
+ preparer = self.identifier_preparer
+ if (self.server_version_info(connection) < (4, 1) and
+ self.use_ansiquotes):
+ # ANSI_QUOTES doesn't affect SHOW CREATE TABLE on < 4.1
+ preparer = MySQLIdentifierPreparer(self)
+
+ self.reflector = reflector = MySQLSchemaReflector(preparer)
sql = self._show_create_table(connection, table, charset)
if sql.startswith('CREATE ALGORITHM'):
@@ -1750,6 +1766,49 @@ class MySQLDialect(default.DefaultDialect):
connection.info['collations'] = collations
return collations
+ def use_ansiquotes(self, useansi):
+ self._use_ansiquotes = useansi
+ if useansi:
+ self.preparer = MySQLANSIIdentifierPreparer
+ else:
+ self.preparer = MySQLIdentifierPreparer
+ # icky
+ if hasattr(self, 'identifier_preparer'):
+ self.identifier_preparer = self.preparer(self)
+ if hasattr(self, 'reflector'):
+ del self.reflector
+
+ use_ansiquotes = property(lambda s: s._use_ansiquotes, use_ansiquotes,
+ doc="True if ANSI_QUOTES is in effect.")
+
+ def _autoset_identifier_style(self, connection, charset=None):
+ """Detect and adjust for the ANSI_QUOTES sql mode.
+
+ If the dialect's use_ansiquotes is unset, query the server's sql mode
+ and reset the identifier style.
+
+ Note that this currently *only* runs during reflection. Ideally this
+ would run the first time a connection pool connects to the database,
+ but the infrastructure for that is not yet in place.
+ """
+
+ if self.use_ansiquotes is not None:
+ return
+
+ row = _compat_fetchone(
+ connection.execute("SHOW VARIABLES LIKE 'sql_mode'",
+ charset=charset))
+ if not row:
+ mode = ''
+ else:
+ mode = row[1] or ''
+ # 4.0
+ if mode.isdigit():
+ mode_no = int(mode)
+ mode = (mode_no | 4 == mode_no) and 'ANSI_QUOTES' or ''
+
+ self.use_ansiquotes = 'ANSI_QUOTES' in mode
+
def _show_create_table(self, connection, table, charset=None,
full_name=None):
"""Run SHOW CREATE TABLE for a ``Table``."""