]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
add error code 1049 for mysql has_table
authorMike Bayer <mike_mp@zzzcomputing.com>
Mon, 6 Feb 2023 18:54:56 +0000 (13:54 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 6 Feb 2023 21:06:11 +0000 (16:06 -0500)
Fixed regression caused by issue :ticket:`9058` which adjusted the MySQL
dialect's ``has_table()`` to again use "DESCRIBE", where the specific error
code raised by MySQL version 8 when using a non-existent schema name was
unexpected and failed to be interpreted as a boolean result.

Fixed the SQLite dialect's ``has_table()`` function to correctly report
False for queries that include a non-None schema name for a schema that
doesn't exist; previously, a database error was raised.

Fixes: #9251
Change-Id: I5ef9cf0887865c3c521d88bca0ba18954a108241

doc/build/changelog/unreleased_20/9251.rst [new file with mode: 0644]
lib/sqlalchemy/dialects/mysql/base.py
lib/sqlalchemy/dialects/sqlite/base.py
lib/sqlalchemy/testing/suite/test_reflection.py

diff --git a/doc/build/changelog/unreleased_20/9251.rst b/doc/build/changelog/unreleased_20/9251.rst
new file mode 100644 (file)
index 0000000..23f743c
--- /dev/null
@@ -0,0 +1,19 @@
+.. change::
+    :tags: bug, mysql, regression
+    :tickets: 9251
+
+    Fixed regression caused by issue :ticket:`9058` which adjusted the MySQL
+    dialect's ``has_table()`` to again use "DESCRIBE", where the specific error
+    code raised by MySQL version 8 when using a non-existent schema name was
+    unexpected and failed to be interpreted as a boolean result.
+
+
+
+.. change::
+    :tags: bug, sqlite
+    :tickets: 9251
+
+    Fixed the SQLite dialect's ``has_table()`` function to correctly report
+    False for queries that include a non-None schema name for a schema that
+    doesn't exist; previously, a database error was raised.
+
index 50e0ec07eaee43cfabf37d1b95dca4f86d6ac905..3e3578df99448ba0b677ba769a4fc0b0f5ddb07d 100644 (file)
@@ -2690,7 +2690,21 @@ class MySQLDialect(default.DefaultDialect):
             ) as rs:
                 return rs.fetchone() is not None
         except exc.DBAPIError as e:
-            if self._extract_error_code(e.orig) == 1146:
+            # https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html  # noqa: E501
+            # there are a lot of codes that *may* pop up here at some point
+            # but we continue to be fairly conservative.  We include:
+            # 1146: Table '%s.%s' doesn't exist - what every MySQL has emitted
+            # for decades
+            #
+            # mysql 8 suddenly started emitting:
+            # 1049: Unknown database '%s'  - for nonexistent schema
+            #
+            # also added:
+            # 1051: Unknown table '%s' - not known to emit
+            #
+            # there's more "doesn't exist" kinds of messages but they are
+            # less clear if mysql 8 would suddenly start using one of those
+            if self._extract_error_code(e.orig) in (1146, 1049, 1051):
                 return False
             raise
 
index e46443a74b4d09591b14496bcc681ad09d596ece..fcabf5bb82d90729ba8cc21d82ca6fbd1e647716 100644 (file)
@@ -2152,6 +2152,11 @@ class SQLiteDialect(default.DefaultDialect):
     def has_table(self, connection, table_name, schema=None, **kw):
         self._ensure_has_table_connection(connection)
 
+        if schema is not None and schema not in self.get_schema_names(
+            connection, **kw
+        ):
+            return False
+
         info = self._get_table_pragma(
             connection, "table_info", table_name, schema=schema
         )
index 2550eff4e81496610bf49ed76bf6ba0b41fb46c1..8b7cb8cbc8309059684d77d62ccc4840ef8c3ae2 100644 (file)
@@ -177,6 +177,15 @@ class HasTableTest(OneConnectionTablesTest):
                 )
             )
 
+    @testing.requires.schemas
+    def test_has_table_nonexistent_schema(self):
+        with config.db.begin() as conn:
+            is_false(
+                config.db.dialect.has_table(
+                    conn, "test_table", schema="nonexistent_schema"
+                )
+            )
+
     @testing.requires.views
     def test_has_table_view(self, connection):
         insp = inspect(connection)