diff options
author | Jason Kirtland <jek@discorporate.us> | 2008-02-05 17:26:35 +0000 |
---|---|---|
committer | Jason Kirtland <jek@discorporate.us> | 2008-02-05 17:26:35 +0000 |
commit | 96549e6b8fd353a82a77938a754bd168a924385b (patch) | |
tree | 829b401c09a47ee52b22a094d171cfdb406aae5c /lib/sqlalchemy/databases/mysql.py | |
parent | dc98505f2f182b099dddcba45c518584e131a039 (diff) | |
download | sqlalchemy-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.py | 75 |
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``.""" |