From dc91c7db7ff32243cd2f6fc04f4e3a6d62f7b11b Mon Sep 17 00:00:00 2001 From: Gord Thompson Date: Fri, 21 Aug 2020 10:29:29 -0600 Subject: Emit v2.0 deprecation warning for "implicit autocommit" "Implicit autocommit", which is the COMMIT that occurs when a DML or DDL statement is emitted on a connection, is deprecated and won't be part of SQLAlchemy 2.0. A 2.0-style warning is emitted when autocommit takes effect, so that the calling code may be adjusted to use an explicit transaction. As part of this change, DDL methods such as :meth:`_schema.MetaData.create_all` when used against a :class:`_engine.Engine` or :class:`_engine.Connection` will run the operation in a BEGIN block if one is not started already. The MySQL and MariaDB dialects now query from the information_schema.tables system view in order to determine if a particular table exists or not. Previously, the "DESCRIBE" command was used with an exception catch to detect non-existent, which would have the undesirable effect of emitting a ROLLBACK on the connection. There appeared to be legacy encoding issues which prevented the use of "SHOW TABLES", for this, but as MySQL support is now at 5.0.2 or above due to :ticket:`4189`, the information_schema tables are now available in all cases. Fixes: #4846 Change-Id: I733a7e0e17477a63607fb9931c87c393bbd7ac57 --- lib/sqlalchemy/dialects/mysql/base.py | 49 +++++++++++++---------------------- 1 file changed, 18 insertions(+), 31 deletions(-) (limited to 'lib/sqlalchemy/dialects') diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py index 0c9859e79..1003eeca6 100644 --- a/lib/sqlalchemy/dialects/mysql/base.py +++ b/lib/sqlalchemy/dialects/mysql/base.py @@ -887,6 +887,7 @@ from collections import defaultdict import re from sqlalchemy import literal_column +from sqlalchemy import text from sqlalchemy.sql import visitors from . import reflection as _reflection from .enumerated import ENUM @@ -938,6 +939,7 @@ from ...sql import compiler from ...sql import elements from ...sql import roles from ...sql import util as sql_util +from ...sql.sqltypes import Unicode from ...types import BINARY from ...types import BLOB from ...types import BOOLEAN @@ -2708,39 +2710,24 @@ class MySQLDialect(default.DefaultDialect): return connection.exec_driver_sql("SELECT DATABASE()").scalar() def has_table(self, connection, table_name, schema=None): - # SHOW TABLE STATUS LIKE and SHOW TABLES LIKE do not function properly - # on macosx (and maybe win?) with multibyte table names. - # - # TODO: if this is not a problem on win, make the strategy swappable - # based on platform. DESCRIBE is slower. - - # [ticket:726] - # full_name = self.identifier_preparer.format_table(table, - # use_schema=True) + if schema is None: + schema = self.default_schema_name - full_name = ".".join( - self.identifier_preparer._quote_free_identifiers( - schema, table_name - ) + rs = connection.execute( + text( + "SELECT * FROM information_schema.tables WHERE " + "table_schema = :table_schema AND " + "table_name = :table_name" + ).bindparams( + sql.bindparam("table_schema", type_=Unicode), + sql.bindparam("table_name", type_=Unicode), + ), + { + "table_schema": util.text_type(schema), + "table_name": util.text_type(table_name), + }, ) - - st = "DESCRIBE %s" % full_name - rs = None - try: - try: - rs = connection.execution_options( - skip_user_error_events=True - ).exec_driver_sql(st) - have = rs.fetchone() is not None - rs.close() - return have - except exc.DBAPIError as e: - if self._extract_error_code(e.orig) == 1146: - return False - raise - finally: - if rs: - rs.close() + return bool(rs.scalar()) def has_sequence(self, connection, sequence_name, schema=None): if not self.supports_sequences: -- cgit v1.2.1